Vue2:警告:避免直接改变道具
Vue2: warning: Avoid mutating a prop directly
我陷入了这样一种情况,即我的子组件(自动完成)需要更新其父组件(曲线)的值,而父组件需要更新其中一个子组件(或完全重新渲染时使用了新的曲线组件)
在我的应用程序中,用户可以 select 曲线组件列表中的曲线。我以前的代码工作正常,除了当用户 select 在列表中编辑另一个曲线时组件自动完成没有更新(组件没有用父值更新它的值)。
此问题现已解决,但我收到此警告:
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:
"value"
此警告的描述准确地解释了我对我的组件的预期行为。尽管有这个警告,这段代码仍然可以正常工作!
这是代码(为简化起见,已删除部分代码)
// curve.vue
<template>
<autocomplete v-model="curve.y"></autocomplete>
</template>
<script>
import Autocomplete from './autocomplete'
export default {
name: 'Curve',
props: {
value: Object
},
computed: {
curve() { return this.value }
},
components: { Autocomplete }
}
</script>
// autocomplete.vue
<template>
<input type="text" v-model="content"/>
</template>
<script>
export default {
name: 'Autocomplete',
props: {
value: {
type: String,
required: true
}
},
computed: {
content: {
get() { return this.value },
set(newValue) { this.value = newValue }
}
}
}
</script>
很多人都收到了同样的警告,我尝试了一些我找到的解决方案,但我无法让它们在我的情况下工作(使用事件,将自动完成的道具类型更改为对象,使用其他计算值,...)
有没有简单的方法可以解决这个问题?我应该忽略这个警告吗?
你可以忽略它,一切都会正常工作,但这是一种不好的做法,这就是 vue 告诉你的。如果您不遵循单一责任原则,调试代码会更加困难。
Vue 建议您,只有拥有数据的组件才能修改它。
不确定为什么事件解决方案 ($emit
) 在您的情况下不起作用,它会抛出错误或什么?
要消除此警告,您还可以使用 .sync
修饰符:
https://vuejs.org/v2/guide/components.html#sync-Modifier
您可以尝试使用代码,在每个组件和组件包装器中遵循 prop
-> local data
-> $emit local data to prop
流程。
ps: $emit('input', ...) 更新了由 v-model
绑定的值(在 props 中)
// curve.vue
<template>
<autocomplete v-model="curve.y"></autocomplete>
</template>
<script>
import Autocomplete from './autocomplete'
export default {
name: 'Curve',
props: {
value: Object
},
data() {
return { currentValue: this.value }
}
computed: {
curve() { return this.currentValue }
},
watch: {
'curve.y'(val) {
this.$emit('input', this.currentValue);
}
},
components: { Autocomplete }
}
</script>
// autocomplete.vue
<template>
<input type="text" v-model="content"/>
</template>
<script>
export default {
name: 'Autocomplete',
props: {
value: {
type: String,
required: true
}
},
data() {
return { currentValue: this.value };
},
computed: {
content: {
get() { return this.value },
set(newValue) {
this.currentValue = newValue;
this.$emit('input', this.currentValue);
}
}
}
}
</script>
我陷入了这样一种情况,即我的子组件(自动完成)需要更新其父组件(曲线)的值,而父组件需要更新其中一个子组件(或完全重新渲染时使用了新的曲线组件)
在我的应用程序中,用户可以 select 曲线组件列表中的曲线。我以前的代码工作正常,除了当用户 select 在列表中编辑另一个曲线时组件自动完成没有更新(组件没有用父值更新它的值)。
此问题现已解决,但我收到此警告:
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: "value"
此警告的描述准确地解释了我对我的组件的预期行为。尽管有这个警告,这段代码仍然可以正常工作!
这是代码(为简化起见,已删除部分代码)
// curve.vue
<template>
<autocomplete v-model="curve.y"></autocomplete>
</template>
<script>
import Autocomplete from './autocomplete'
export default {
name: 'Curve',
props: {
value: Object
},
computed: {
curve() { return this.value }
},
components: { Autocomplete }
}
</script>
// autocomplete.vue
<template>
<input type="text" v-model="content"/>
</template>
<script>
export default {
name: 'Autocomplete',
props: {
value: {
type: String,
required: true
}
},
computed: {
content: {
get() { return this.value },
set(newValue) { this.value = newValue }
}
}
}
</script>
很多人都收到了同样的警告,我尝试了一些我找到的解决方案,但我无法让它们在我的情况下工作(使用事件,将自动完成的道具类型更改为对象,使用其他计算值,...)
有没有简单的方法可以解决这个问题?我应该忽略这个警告吗?
你可以忽略它,一切都会正常工作,但这是一种不好的做法,这就是 vue 告诉你的。如果您不遵循单一责任原则,调试代码会更加困难。
Vue 建议您,只有拥有数据的组件才能修改它。
不确定为什么事件解决方案 ($emit
) 在您的情况下不起作用,它会抛出错误或什么?
要消除此警告,您还可以使用 .sync
修饰符:
https://vuejs.org/v2/guide/components.html#sync-Modifier
您可以尝试使用代码,在每个组件和组件包装器中遵循 prop
-> local data
-> $emit local data to prop
流程。
ps: $emit('input', ...) 更新了由 v-model
绑定的值(在 props 中)// curve.vue
<template>
<autocomplete v-model="curve.y"></autocomplete>
</template>
<script>
import Autocomplete from './autocomplete'
export default {
name: 'Curve',
props: {
value: Object
},
data() {
return { currentValue: this.value }
}
computed: {
curve() { return this.currentValue }
},
watch: {
'curve.y'(val) {
this.$emit('input', this.currentValue);
}
},
components: { Autocomplete }
}
</script>
// autocomplete.vue
<template>
<input type="text" v-model="content"/>
</template>
<script>
export default {
name: 'Autocomplete',
props: {
value: {
type: String,
required: true
}
},
data() {
return { currentValue: this.value };
},
computed: {
content: {
get() { return this.value },
set(newValue) {
this.currentValue = newValue;
this.$emit('input', this.currentValue);
}
}
}
}
</script>