admin管理员组

文章数量:1332865

What's the proper way to access puted properties of child ponents? Below is a simplified example of what I'm trying to achieve (also available on 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,
        }
    },
    puted: {
        sum() {
            const s = Number(this.value.a) + Number(this.value.b)
            // WARNING eslint - vue:no-side-effects-in-puted-properties
            this.value.sum = s;
            return s;
        }
    },
    methods: {
        die() {
            this.$emit('die');
        }
    }
};

new Vue({
    el: '#app',
    data: {
        foobars: [{
            a: '5',
            b: '6'
        }],
    },
    ponents: {
        FoobarWidget,
    },
    puted: {
        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=".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>

What's the proper way to access puted properties of child ponents? Below is a simplified example of what I'm trying to achieve (also available on 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,
        }
    },
    puted: {
        sum() {
            const s = Number(this.value.a) + Number(this.value.b)
            // WARNING eslint - vue:no-side-effects-in-puted-properties
            this.value.sum = s;
            return s;
        }
    },
    methods: {
        die() {
            this.$emit('die');
        }
    }
};

new Vue({
    el: '#app',
    data: {
        foobars: [{
            a: '5',
            b: '6'
        }],
    },
    ponents: {
        FoobarWidget,
    },
    puted: {
        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./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>

As one can see after trying this example, it mostly works - except it doesn't reflect the changes very well in parent ponent (generated JSON) after changing the values in child ponents (a, b, and puted sum).

The question seems similar to SO: Computed property on child ponent props, however OP of that question had a puted value doing string formatting, making use of Vue filters a good solution. This is not the case here - the sum() puted property can be an arbitrary function, which is needed to be accessed both in parent and in child ponents.

The way I did it above, by modifying the prop object by adding a sum property to it when it's reputed is definitely not the right way to do it, hence my question. Not only it works wonkily, but it also produces an ESLint warning (the WARNING ment in code above).

Share Improve this question edited Feb 23, 2018 at 15:34 Zaroth asked Feb 23, 2018 at 15:00 ZarothZaroth 5787 silver badges19 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 2

I would suggest you're taking the wrong approach here. If you want a property that is the sum of the values on the object, add that property to the object, not to the ponent.

Here is an example.

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],
  },
  ponents: {
    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./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>

Using this approach you never need to access the puted property of the ponent.

The reason your parent doesn't update is that you're adding a property to an object, which Vue doesn't detect.

Instead of

    sum() {
        const s = Number(this.value.a) + Number(this.value.b)
        // WARNING eslint - vue:no-side-effects-in-puted-properties
        this.value.sum = s;
        return s;
    }

You would do

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

Notwithstanding the code smell of side effects in a puted, and updating values in a prop, which suggests you ought to be doing something differently.

本文标签: javascriptAccessing computed properties of child components in VueStack Overflow