我开始了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的新手,所以我完全不知道如何修复它。有人知道如何(请解释为什么)解决这个问题吗?


当前回答

Vue只是警告您:您更改了组件中的道具,但当父组件重新呈现时,“list”将被覆盖,您将丢失所有更改。所以这样做是危险的。

使用computed属性,如下所示:

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

其他回答

Vue.js的道具不能被改变,因为这被认为是Vue中的反模式。

您需要采取的方法是在组件上创建一个引用list的原始prop属性的data属性

props: ['list'],
data: () {
  return {
    parsedList: JSON.parse(this.list)
  }
}

现在传递给组件的列表结构通过组件的data属性被引用和改变:-)

如果您希望做的不仅仅是解析列表属性,那么请使用Vue组件的computed属性。 这允许你对你的道具做出更深入的变化。

props: ['list'],
computed: {
  filteredJSONList: () => {
    let parsedList = JSON.parse(this.list)
    let filteredList = parsedList.filter(listItem => listItem.active)
    console.log(filteredList)
    return filteredList
  }
}

上面的示例将解析您的列表道具,并将其过滤为仅活跃的list-tems,将其记录为schnitts和giggles并返回它。

注意:数据和计算属性在模板中引用相同

<pre>{{parsedList}}</pre>

<pre>{{filteredJSONList}}</pre>

很容易认为计算属性(作为一个方法)需要被调用…它不

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

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

并更改listClone的值。

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

如果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>

我想给出这个答案,这有助于避免使用大量的代码,观察者和计算属性。在某些情况下,这可能是一个很好的解决方案:

道具是用来提供单向交流的。

当你有一个带有道具的模态显示/隐藏按钮时,对我来说最好的解决方案是发出一个事件:

<button @click="$emit('close')">Close Modal</button>

然后添加监听器到模态元素:

<modal :show="show" @close="show = false"></modal>

(在这种情况下,道具显示可能是不必要的,因为你可以直接在基本模式上使用简单的v-if="show")

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