我开始了https://laracasts.com/series/learning-vue-step-by-step系列。我在Vue、Laravel和AJAX的课程上停了下来,出现了这个错误:

Vue .js:2574 [Vue警告]:避免直接改变道具,因为每当父组件重新呈现时,该值将被覆盖。相反,应该使用基于道具值的数据或计算属性。道具被突变:"list"(在组件中找到)

我在main.js中有这段代码

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    created() {
        this.list = JSON.parse(this.list);
    }
});
new Vue({
    el: '.container'
})

我知道,当我覆盖列表道具时,问题是在created(),但我是Vue的新手,所以我完全不知道如何修复它。有人知道如何(请解释为什么)解决这个问题吗?


当前回答

您不应该在子组件中更改props的值。 如果你真的需要改变它,你可以使用.sync。 就像这样

<您的组件:list.sync = "列表" > < /组件>

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    created() {
        this.$emit('update:list', JSON.parse(this.list))
    }
});
new Vue({
    el: '.container'
})

其他回答

道具下降,事件上升。这就是Vue的模式。关键是,如果你试图变异从父母传递的道具。它不会工作,只会被父组件重复覆盖。子组件只能发出一个事件来通知父组件做某事。如果你不喜欢这些限制,你可以使用VUEX(实际上这种模式会吸收复杂的组件结构,你应该使用VUEX!)

如果你想改变道具-使用对象。

<component :model="global.price"></component>

组件:

props: ['model'],
methods: {
  changeValue: function() {
    this.model.value = "new value";
  }
}

答案很简单,您应该通过将值分配给一些局部组件变量(可以是数据属性,用getter、setter或观察者计算)来打破直接的prop突变。

这里有一个使用监视器的简单解决方案。

<template>
  <input
    v-model="input"
    @input="updateInput" 
    @change="updateInput"
  />

</template>

<script>
  export default {
  props: {
    value: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      input: '',
    };
  },
  watch: {
    value: {
      handler(after) {
        this.input = after;
      },
      immediate: true,
    },
  },
  methods: {
    updateInput() {
      this.$emit('input', this.input);
    },
  },
};
</script>

我用它来创建任何数据输入组件,它工作得很好。从父元素发送的任何新数据(v-model(ed))都将被值监视器监视并分配给输入变量,一旦接收到输入,我们就可以捕捉该操作并向父元素发出输入,表明数据是从表单元素输入的。

除上述问题外,如有下列问题:

如果props值不是必需的,因此不总是返回,则传递的数据将返回undefined(而不是空)。这可能会混乱<select>默认值,我通过检查是否在beforeMount()设置的值来解决它(如果没有设置它)如下:

JS:

export default {
        name: 'user_register',
        data: () => ({
            oldDobMonthMutated: this.oldDobMonth,
        }),
        props: [
            'oldDobMonth',
            'dobMonths', //Used for the select loop
        ],
        beforeMount() {
           if (!this.oldDobMonth) {
              this.oldDobMonthMutated = '';
           } else {
              this.oldDobMonthMutated = this.oldDobMonth
           }
        }
}

Html:

<select v-model="oldDobMonthMutated" id="dob_months" name="dob_month">

 <option selected="selected" disabled="disabled" hidden="hidden" value="">
 Select Month
 </option>

 <option v-for="dobMonth in dobMonths"
  :key="dobMonth.dob_month_slug"
  :value="dobMonth.dob_month_slug">
  {{ dobMonth.dob_month_name }}
 </option>

</select>

根据VueJs 2.0,您不应该改变组件内部的道具。它们只会被父母变异。因此,您应该在数据中定义不同名称的变量,并通过观察实际的道具来更新它们。 如果列表道具被父元素更改,您可以解析它并将其分配给mutableList。这里有一个完整的解决方案。

Vue.component('task', {
    template: ´<ul>
                  <li v-for="item in mutableList">
                      {{item.name}}
                  </li>
              </ul>´,
    props: ['list'],
    data: function () {
        return {
            mutableList = JSON.parse(this.list);
        }
    },
    watch:{
        list: function(){
            this.mutableList = JSON.parse(this.list);
        }
    }
});

它使用mutableelist来呈现模板,这样就可以在组件中保证列表道具的安全。