Vue.js - 计算属性不更新 - 子组件

4

我创建了一个名为DefaultButton的简单组件。 它基于在创建此组件时设置的属性。 问题在于,在挂载后,它不会对与属性中的对象“defaultbutton”相关的更改做出反应。

<template>
  <button :class="buttonClass" v-if="isActive" @click="$emit('buttonAction', defaultbutton.id)" >
    {{ this.defaultbutton.text }} 
  </button>
  <button :class="buttonClass" v-else disabled="disabled">
    {{ this.defaultbutton.text }} 
  </button>
</template>


<script>
export default {
  name: "defaultbutton",
  props: {
    defaultbutton: Object
  },
  computed: {
    buttonClass() {
      return `b41ngt ${this.defaultbutton.state}`;
    },
    isActive() {
      return (this.defaultbutton.state === "BUTTON_ACTIVE" || this.defaultbutton.state === "BUTTON_ACTIVE_NOT_CHOSEN");
    }
  }
};
</script>

作为父组件的以下组件:

<template>
    <div v-if="state_items.length == 2" class="ui placeholder segment">
        {{ this.state_items[0].state }}
        {{ this.state_items[1].state }}
        {{ this.current_active_state }}
      <div class="ui two column very relaxed stackable grid">
        <div class="column">
            <default-button :defaultbutton="state_items[0]" @buttonAction="changecurrentstate(0)"/>
        </div>
        <div class="middle aligned column">
            <default-button :defaultbutton="state_items[1]" @buttonAction="changecurrentstate(1)"/>
        </div>
      </div>
      <div class="ui vertical divider">
        Or
      </div>
    </div>

</template>


<script type="text/javascript">
    import DefaultButton from '../Button/DefaultButton'

    export default {
        name: 'changestatebox',
        data() {
            return {
                current_active_state: 1
            }
        },
        props: {
            state_items: []
        },
        components: {
            DefaultButton
        },
        methods: {
            changecurrentstate: function(index) {
                if(this.current_active_state != index) {
                    this.state_items[this.current_active_state].state = 'BUTTON_ACTIVE_NOT_CHOSEN';
                    this.state_items[index].state = 'BUTTON_ACTIVE';
                    this.current_active_state = index;
                }
            },
        },
        mounted: function () {
            this.state_items[0].state = 'BUTTON_ACTIVE';
            this.state_items[1].state = 'BUTTON_ACTIVE_NOT_CHOSEN';
        }
    }

</script>

它清楚地展示了使用:

{{ this.state_items[0].state }}
{{ this.state_items[1].state }}
{{ this.current_active_state }}

这些项目的状态正在被更改,但我无法在生成的“DefaultButtons”上看到任何结果。包含在这些组件中的对象类没有被更改。

@edit

我完全改变了数据传递方式。由于这个改变,我放弃了使用数组,而是使用了两个完全不相关的对象。结果是一样的 - 子组件对象的类没有被改变。

DefaulButton.vue:

<template>
  <button :class="buttonClass" v-if="isActive" @click="$emit('buttonAction', defaultbutton.id)" >
    {{ this.defaultbutton.text }} 
  </button>
  <button :class="buttonClass" v-else disabled="disabled">
    {{ this.defaultbutton.text }} 
  </button>
</template>

<style lang="scss">
  import './DefaultButton.css';
</style>

<script>
export default {
  name: "defaultbutton",
  props: {
    defaultbutton: {
      type: Object,
      default: () => ({
        id: '',
        text: '',
        state: '',
      })
    }
  },
  computed: {
    buttonClass() {
      return `b41ngt ${this.defaultbutton.state}`;
    },
    isActive() {
      return (this.defaultbutton.state === "BUTTON_ACTIVE" ||
        this.defaultbutton.state === "BUTTON_ACTIVE_NOT_CHOSEN");
    }
  }
};
</script>

ChangeStateBox.vue:

<template>
    <div class="ui placeholder segment">
        {{ this.state_first.state }}
        {{ this.state_second.state }}
        {{ this.current_active_state }}
      <div class="ui two column very relaxed stackable grid">
        <div class="column">
            <default-button :defaultbutton="state_first" @buttonAction="changecurrentstate(0)"/>
        </div>
        <div class="middle aligned column">
            <default-button :defaultbutton="state_second" @buttonAction="changecurrentstate(1)"/>
        </div>
      </div>
      <div class="ui vertical divider">
        Or
      </div>
    </div>

</template>

<script type="text/javascript">
    import DefaultButton from '../Button/DefaultButton'

    export default {
        name: 'changestatebox',
        data() {
            return {
                current_active_state: 1
            }
        },
        props: {
            state_first: {
                type: Object,
                default: () => ({
                  id: '',
                  text: ''  
                })
            },
            state_second: {
                type: Object,
                default: () => ({
                  id: '',
                  text: ''  
                })
            },
        },
        components: {
            DefaultButton
        },
        methods: {
            changecurrentstate: function(index) {
                if(this.current_active_state != index) {
                    if(this.current_active_state == 1){

                        this.$set(this.state_first, 'state', "BUTTON_ACTIVE_NOT_CHOSEN");
                        this.$set(this.state_second, 'state', "BUTTON_ACTIVE");

                    } else {

                        this.$set(this.state_first, 'state', "BUTTON_ACTIVE");
                        this.$set(this.state_second, 'state', "BUTTON_ACTIVE_NOT_CHOSEN");

                    }
                    this.current_active_state = index;
                }
            },
        },
        created: function () {
            this.state_first.state = 'BUTTON_ACTIVE';
            this.state_second.state = 'BUTTON_ACTIVE_NOT_CHOSEN';
        }
    }
</script>

你声明了你的prop错误。defaultbutton应该是一个对象,而required应该是该对象中的一个条目。 - Roy J
我已经进行了更改,以使required不再存在,但结果是一样的——似乎默认按钮的工作方式并未引用父级数据。 - Artur Drożdżyk
3个回答

2
你的主要问题在于你改变按钮状态的方式,根据Vue的数组变化检测,Vue无法通过索引检测到变异。
由于JavaScript的限制,Vue无法检测到以下数组的更改: - 当您直接使用索引设置项目时,例如vm.items[indexOfItem] = newValue - 当您修改数组的长度时,例如vm.items.length = newLength

2
您声明 props 的方式有误,它要么是由 prop 名称组成的数组,要么是一个对象,其中每个条目都声名了其类型,或者是一个对象,其中每个条目都声明了多个属性。在此,您使用了:
    props: {
        state_items: []
    },

但是为了提供默认值,应该这样做

    props: {
        state_items: {
            type: Array,
            default: []
        }
    },

但是你的问题很可能是你以一种导致Vue无法检测到变化的方式突变了state_items


1

如果有人遇到相同的问题:

@Roy J和@DobleL都是正确的。

这个问题的原因与状态对象的错误初始化有关。

根据文档:

Vue cannot detect property addition or deletion. 
Since Vue performs the getter/setter conversion process during instance
initialization, a property must be present in the 
data object in order for Vue to convert it and make it reactive. 

在阅读这句话之前,我通常会以下列对象作为初始数据:

var local_state_first = {
  id: '1',
  text: 'Realized',
};

var local_state_second = {
    id: '2',
    text: 'Active'  
};

而正确的版本应如下所示:

var local_state_first = {
  id: '1',
  text: 'Realized',
  state: 'BUTTON_ACTIVE'
};

var local_state_second = {
  id: '2',
  text: 'Active',
  state: 'BUTTON_ACTIVE'
};

将主要组件声明为:

<change-state-box :state_first="local_state_first" :state_second="local_state_second" @buttonAction="onbuttonAction"/>

代码的其余部分保持不变(请查看我主贴中的@edit标记)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接