我开始了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分配给new变量。

data () {
    return {
        listClone: this.list
    }
}

其他回答

您应该始终避免在vue或任何其他框架中改变道具。您可以采用的方法是将其复制到另一个变量中。

为例。 //而不是替换this的值。List使用不同的变量

这一点。new_data_variable = JSON.parse(this.list)

我也遇到过这个问题。警告消失后,我使用$on和$emit。 它类似于使用$on和$emit来将数据从子组件发送到父组件。

再加上最好的答案,

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    data: function () {
        return {
            mutableList: JSON.parse(this.list);
        }
    }
});

通过数组设置道具是为了开发/原型,在生产中确保设置道具类型(https://v2.vuejs.org/v2/guide/components-props.html),并设置一个默认值,以防道具没有被父元素填充。

Vue.component('task', {
    template: '#task-template',
    props: {
      list: {
        type: String,
        default() {
          return '{}'
        }
      }
    },
    data: function () {
        return {
            mutableList: JSON.parse(this.list);
        }
    }
});

这样你至少可以在mutableList中得到一个空对象,而不是JSON。如果未定义,则解析错误。

答案很简单,您应该通过将值分配给一些局部组件变量(可以是数据属性,用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))都将被值监视器监视并分配给输入变量,一旦接收到输入,我们就可以捕捉该操作并向父元素发出输入,表明数据是从表单元素输入的。

不要直接更改组件中的道具。如果你需要改变它,设置一个新的属性,像这样:

data() {
  return {
    listClone: this.list
  }
}

并更改listClone的值。