我学习vue已有几天了,我正在尝试在父母之间传递数据/道具。 现在,我有以下孩子:
<template>
<div>
<input v-model="name1" placeholder="string">
<input v-model="number1" placeholder="number">
<p v-text="name1"></p>
<p v-text="number1"></p>
</div>
</template>
<script>
export default {
name: "child",
props: {
name1 : String,
number1 : Number
}
}
</script>
然后是父级:
<template>
<div>
<child/>
</div>
</template>
<script>
import child from "@/components/complexComponent4/child.vue"
export default{
name: "parent",
components: {
child
}
}
</script>
现在,当我在输入字段中输入一些文本时,它会正确显示在段落中,因为绑定到段落的道具已更改。 但是,我收到此警告:
[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: "name1"
found in
---> <Child>
<Parent> at src/components/complexComponent4/parent.vue
<MyComplexView4.vue> at src/views/myComplexView4.vue
<App> at src/App.vue
<Root>
我在互联网上的许多地方以及文档中都读到了有关此错误的信息,我发现现在将muting props视为反模式: https://michaelnthiessen.com/avoid-mutating-prop-directly
不幸的是,我没有真正发现任何特定的东西和/或对如何解决这个问题没有帮助。特别是在vue上下文中,以不同方式处理原始数据和对象/数组(对象/数组通过引用传递)。
v型模型似乎在利用vue的力量方面起着重要作用,因为它启用了双向绑定。因此,我不想完全省略它,除非它的使用变得如此困难,以致不能证明其收益。答案 0 :(得分:2)
如警告所述,您应该避免在子组件中直接对道具 进行突变。 因此,您应该从子级向父级发出一个事件,以使父级知道prop值已更改。父母会更改道具并将其传递给孩子。
为此,Vue中有一种语法糖,称为.sync修饰符。
所以您的组件可能是这样的。 孩子:
<template>
<div>
<input
:value="name1"
@change="$emit('update:name1', $event.target.value)"
placeholder="string"
/>
<input
:value="number1"
@change="$emit('update:number1', $event.target.value)"
placeholder="number"
/>
<p v-text="name1"></p>
<p v-text="number1"></p>
</div>
</template>
<script>
export default {
name: "child",
props: {
name1 : String,
number1 : Number
}
}
</script>
和父母:
<template>
<div>
<child :name1.sync="name1" :number1.sync="number1"/>
</div>
</template>
<script>
import child from "@/components/complexComponent4/child.vue"
export default{
name: "parent",
components: {
child
},
data() {
return {
name1: '',
number1: ''
}
}
}
</script>
或者对于更复杂的情况,您可以在子组件中使用v-model和带有setter的计算属性:
<template>
<div>
<input
v-model="computedName1"
placeholder="string"
/>
<input
v-model="computedNumber1"
placeholder="number"
/>
<p v-text="name1"></p>
<p v-text="number1"></p>
</div>
</template>
<script>
export default {
name: "child",
props: {
name1 : String,
number1 : Number
},
computed: {
computedName1: {
get() { return this.name1 },
set(value) {
// some logic
this.$emit('update:name1', value)
},
computedNumber1: {
get() { return this.number1 },
set(value) {
// some logic
this.$emit('update:number1', value)
}
}
}
}
</script>
答案 1 :(得分:1)
如果您打算更改传递给子对象的prop,请先将其分配给子数据。
<template>
<div>
<input v-model="name" placeholder="string">
<input v-model="number" placeholder="number">
<p v-text="name"></p>
<p v-text="number"></p>
</div>
</template>
<script>
export default {
name: "child",
data() {
return {
name: null,
number: null
}
},
props: {
name1 : String,
number1 : Number
},
mounted() {
this.name = this.name1;
this.number = this.number1;
}
}
</script>
更改数据后,您可以将这些更改发送给父组件
父母
<child :number1.sync="number1" :name1.sync="name1" />
孩子
watch: {
name: value => this.$emit('update:name1', value)
number : value => this.$emit('update:number1', value)
},
父母
<child :number1="number1" :name1="name1" @changeNumber="value => number1 = value" @changeName="value => name1 = value" />
孩子
watch: {
name: value => this.$emit('changeName', value)
number : value => this.$emit('updateNumber', value)
},
答案 2 :(得分:0)
vue.js的准则是,您可以使用道具自动更改父级中子级中的数据,反之亦然。为了改变父组件的数据,子组件应该使用事件。您可以考虑分别为name1和number1使用两个不同的组件,并通过使这些组件适用于v-model
(如here所述)以双向方式绑定值。