访问子组件的计算属性的正确方法是什么?以下是我要实现的简化示例(也可以在JSFiddle上获得):
const FoobarWidget = {
template: '<li>a: <input type="text" v-model="value.a" style="width:2em;"> b: <input type="text" v-model="value.b" style="width:2em;"> sum: {{this.sum}} <button @click="die">x</button></li>',
props: {
value: {
type: Object,
required: true,
}
},
computed: {
sum() {
const s = Number(this.value.a) + Number(this.value.b)
// WARNING eslint - vue:no-side-effects-in-computed-properties
this.value.sum = s;
return s;
}
},
methods: {
die() {
this.$emit('die');
}
}
};
new Vue({
el: '#app',
data: {
foobars: [{
a: '5',
b: '6'
}],
},
components: {
FoobarWidget,
},
computed: {
myJson() {
return JSON.stringify(this.foobars, null, 2);
}
},
methods: {
addNew() {
this.foobars.push({
a: '1',
b: '2'
});
},
foobarDead(index) {
this.foobars.splice(index, 1);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<button @click="addNew()">add foobar</button>
<h3>Foobars</h3>
<ul>
<foobar-widget v-for="(foobar, index) in foobars" :key="index" @die="foobarDead(index)" v-model="foobars[index]"/>
</ul>
<h3>JSON</h3>
<pre>{{myJson}}</pre>
</div>
正如尝试这个示例后所看到的,它大部分都可以工作-只是在更改子组件(a,b和计算所得的和)中的值后,它不能很好地反射(reflect)父组件(生成的JSON)中的更改。
这个问题似乎类似于SO: Computed property on child component props,但是该问题的OP在进行字符串格式化时具有计算值,因此使用Vue过滤器是一个很好的解决方案。这里不是这种情况-
sum()
计算的属性可以是任意函数,需要在父组件和子组件中都可以访问该函数。我上面的方法是通过在重新计算 Prop 对象时添加
sum
属性来修改 Prop 对象,但这绝对不是正确的方法,因此,我提出了问题。它不仅可以正常工作,而且还会产生ESLint警告(上面代码中的WARNING
注释)。 最佳答案
我建议您在这里采用错误的方法。如果要使用的属性是对象值的总和,请将该属性添加到对象,而不是组件。
这是一个例子。
const FoobarWidget = {
template: '<li>a: <input type="text" v-model="value.a" style="width:2em;"> b: <input type="text" v-model="value.b" style="width:2em;"> sum: {{value.sum}} <button @click="die">x</button></li>',
props: {
value: {
type: Object,
required: true,
}
},
methods: {
die() {
this.$emit('die');
}
}
};
const foo = {
a: 5,
b: 6,
// define your property here
get sum() {
return +this.a + +this.b
}
}
new Vue({
el: '#app',
data: {
foobars: [foo],
},
components: {
FoobarWidget,
},
methods: {
addNew() {
this.foobars.push({
a: '1',
b: '2',
get sum() {
return +this.a + +this.b;
}
});
},
foobarDead(index) {
this.foobars.splice(index, 1);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<button @click="addNew()">add foobar</button>
<h3>Foobars</h3>
<ul>
<foobar-widget v-for="(foobar, index) in foobars" :key="index" @die="foobarDead(index)" v-model="foobars[index]" />
</ul>
<h3>JSON</h3>
<pre>{{foobars}}</pre>
</div>
使用这种方法,您无需访问组件的计算属性。