簡體   English   中英

在 Vue 中訪問子組件的計算屬性

[英]Accessing computed properties of child components in Vue

訪問子組件的計算屬性的正確方法是什么? 下面是我想要實現的簡化示例(也可在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 和計算總和)中的值之后,它不能很好地反映父組件(生成的 JSON)中的更改。

這個問題似乎類似於SO: Computed property on child component props ,但是該問題的 OP 有一個計算值來進行字符串格式化,因此使用 Vue 過濾器是一個很好的解決方案。 這不是這里的情況 - sum()計算屬性可以是任意函數,需要在父組件和子組件中訪問。

我在上面做的方式,通過在重新計算時添加sum屬性來修改 prop 對象,這絕對不是正確的方法,因此我的問題。 它不僅可以正常工作,而且還會產生 ESLint 警告(上面代碼中的WARNING注釋)。

你的父母沒有更新的原因是你正在向一個對象添加一個屬性,而 Vue 沒有檢測到.

代替

    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;
    }

你會做

sum() {
    const s = Number(this.value.a) + Number(this.value.b)
    this.$set(this.value, 'sum', s);
    return s;
}

盡管計算和更新道具中的值有副作用的代碼氣味,這表明您應該做一些不同的事情。

我建議你在這里采取錯誤的方法。 如果您想要一個屬性是對象上的值的總和,請將該屬性添加到對象,而不是組件。

這是一個例子。

 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>

使用這種方法,您永遠不需要訪問組件的計算屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM