Vue 2 - 变异道具vue-warn
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 2 - 变异道具vue-warn相关的知识,希望对你有一定的参考价值。
我开始了https://laracasts.com/series/learning-vue-step-by-step系列。我停止了Vue,Laravel和AJAX这个错误:
vue.js:2574 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "list" (found in component <task>)
我在main.js中有这段代码
Vue.component('task', {
template: '#task-template',
props: ['list'],
created() {
this.list = JSON.parse(this.list);
}
});
new Vue({
el: '.container'
})
我知道当我覆盖列表道具时问题出在created()中,但我是Vue的新手,所以我完全不知道如何解决它。任何人都知道如何(并请解释原因)来修复它?
这与mutating a prop locally is considered an anti-pattern in Vue 2的事实有关
如果你想在本地改变一个道具,你现在应该做的是在你的data
中声明一个使用props
值作为其初始值然后改变副本的字段:
Vue.component('task', {
template: '#task-template',
props: ['list'],
data: function () {
return {
mutableList: JSON.parse(this.list);
}
}
});
你可以在Vue.js official guide上阅读更多相关信息
注1:请注意you should not use the same name for your prop
and data
,即:
data: function () { return { list: JSON.parse(this.list) } // WRONG!!
注2:自I feel there is some confusion关于props
和反应性,我建议你看看this线程
如果你想改变道具 - 使用对象。
<component :model="global.price"></component>
零件:
props: ['model'],
methods: {
changeValue: function() {
this.model.value = "new value";
}
}
你需要像这样添加计算方法
component.vue
props: ['list'],
computed: {
listJson: function(){
return JSON.parse(this.list);
}
}
单向数据流,根据https://vuejs.org/v2/guide/components.html,组件遵循单向数据流,所有道具形成子属性和父属性之间的单向向下绑定,当父属性更新时,它将向下流向孩子而不是反过来,这可以防止子组件意外地改变父组件,这可能会使您的应用程序的数据流更难理解。
此外,每次更新父组件时,子组件中的所有道具都将使用最新值进行刷新。这意味着您不应该尝试改变子组件内的prop。如果你这样做.vue会在控制台中警告你。
通常有两种情况,它很容易改变道具:道具用于传递初始值;子组件之后想要将它用作本地数据属性。 prop是作为需要转换的原始值传递的。这些用例的正确答案是:定义使用prop的初始值作为其初始值的本地数据属性:
props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}
定义根据prop的值计算的计算属性:
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
Vue.js道具不会被改变,因为它被认为是Vue中的反模式。
您需要采取的方法是在组件上创建一个引用list的原始prop属性的数据属性
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
}
}
上面的例子解析你的列表道具并将其过滤到只有活动的列表文本,将其记录下来用于schnitts和giggles并返回它。
注意:data
和computed
属性在模板中引用相同,例如
<pre>{{parsedList}}</pre>
<pre>{{filteredJSONList}}</pre>
可以很容易地认为需要调用computed
属性(作为一种方法)......它不需要
Vue.component('task', {
template: '#task-template',
props: ['list'],
computed: {
middleData() {
return this.list
}
},
watch: {
list(newVal, oldVal) {
console.log(newVal)
this.newList = newVal
}
},
data() {
return {
newList: {}
}
}
});
new Vue({
el: '.container'
})
也许这将满足您的需求。
添加到最佳答案,
Vue.component('task', {
template: '#task-template',
props: ['list'],
data: function () {
return {
mutableList: JSON.parse(this.list);
}
}
});
通过数组设置道具是用于开发/原型设计,在生产中确保设置道具类型(https://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.parse错误,如果它是未定义的。
Vue.js认为这是一种反模式。例如,声明和设置一些道具,如
this.propsVal = 'new Props Value'
因此,要解决此问题,您必须从props获取值到数据或Vue实例的计算属性,如下所示:
props: ['propsVal'],
data: function() {
return {
propVal: this.propsVal
};
},
methods: {
...
}
这肯定会奏效。
除上述内容外,对于有以下问题的其他人:
“如果不需要道具值,因此不总是返回,传递的数据将返回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>
Vue只是警告你:你改变组件中的prop,但是当父组件重新渲染时,“list”将被覆盖,你将丢失所有的更改。所以这样做很危险。
使用计算属性,如下所示:
Vue.component('task', {
template: '#task-template',
props: ['list'],
computed: {
listJson: function(){
return JSON.parse(this.list);
}
}
});
如果你正在使用Lodash,你可以在返回之前克隆道具。如果您在父项和子项上修改该prop,则此模式很有用。
假设我们在组件网格上有道具列表。
在父组件中
<grid :list.sync="list"></grid>
在子组件中
props: ['list'],
methods:{
doSomethingOnClick(entry){
let modifiedList = _.clone(this.list)
modifiedList = _.uniq(modifiedList) // Removes duplicates
this.$emit('update:list', modifiedList)
}
}
道具失败,事件发生了。这是Vue的模式。关键是,如果你试图改变从父母传递的道具。它不起作用,它只是被父组件重复覆盖。子组件只能发出事件来通知父组件做某事。如果您不喜欢这些限制,可以使用VUEX(实际上这种模式会吸引复杂的组件结构,您应该使用VUEX!)
您不应该更改子组件中props的值。如果你真的需要改变它,你可以使用.sync
。像这样
<your-component :list.sync="list"></your-component>
Vue.component('task', {
template: '#task-template',
props: ['list'],
created() {
this.$emit('update:list', JSON.parse(this.list))
}
});
new Vue({
el: '.container'
})
Vue模式很简单:props
down和events
up。这听起来很直接,但在编写自定义组件时很容易忘记。
从Vue 2.2.0开始,您可以使用道具在 vue js 中发生变异