Difference between computed property and normal data in Vue.js

时光总嘲笑我的痴心妄想 提交于 2020-01-04 22:45:12

问题


I observed that when a normal property that came from data() and a computed property that is derived from it are passed through an event, the former keeps its reactivity while the latter loses it.

I set up the following test case for it (also as a JSFiddle if you prefer that):

const EventBus = new Vue();

Vue.component('comp', {
  data() {
    return {
      arrData: ['a', 'b']
    };
  },
  computed: {
    arrComputed() {
      return this.arrData.map((e) => e.toUpperCase());
    }
  },
  template: `
  <div>
    <div>Original array: {{ arrData }}</div>
    <div>Computed array: {{ arrComputed }}</div>
    <button @click="remove('a')">Remove a</button>
    <button @click="remove('b')">Remove b</button>
    <button @click="pass">Pass through event</button>
    <button @click="reset">Start over soft</button>
    <button @click="resetHard">Start over hard</button>
  </div>`,
  methods: {
    remove(name) {
      name = name.toLowerCase();
      if(this.arrData.indexOf(name) != -1) {
        this.$delete(this.arrData, this.arrData.indexOf(name));
      }
    },
    pass() {
      EventBus.$emit('pass', this.arrData, this.arrComputed);
    },
    reset() {
      this.$set(this.arrData, 0, 'a');
      this.$set(this.arrData, 1, 'b');
    },
    resetHard() {
      this.arrData = ['a','b'];
    }
  }
});

Vue.component('othercomp', {
  data() {
    return {
      items1: [],
      items2: []
    }
  },
  mounted() {
		EventBus.$on('pass', this.receive);
  },
  template: `
  <div>
    <div>Original array: {{items1}}</div>
    <div>Computed array: {{items2}}</div>
  </div>`,
  methods: {
    receive(items1, items2) {
      this.items1 = items1;
      this.items2 = items2;
    }
  }
});

var app = new Vue({
  el: '#app',
  components:['comp', 'othercomp']
})
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <comp></comp>
  <othercomp></othercomp>
</div>

How is a computed different from a normal property so that this difference in behaviour occurs?

I learned from a previous question that passing reactive objects around like this is bad practice and that I should use a getter function instead, however I'd still like to know why this difference occurs.


回答1:


I would not expect this to work. By returning the results of map() you are passing a copy of the reactive array to the other component. This copy will not react to changes of the original array — it's a totally different array. And even though the computed property will update when arrData changes, it won't automatically send another event to the second component telling it to update it's data array. I would think you'll need a computed property on both components — you could do this in a DRY fashion with a mixin or filter (which is probably more appropriate in this case).

You could fire the event in the computed function. But this seems pretty hacky to me:

arrComputed() { 
   let newArray = this.arrData.map((e) => e.toUpperCase());
   EventBus.$emit('pass', this.arrData, newArray);
   return newArray
}



回答2:


I observed that when a normal property that came from data() and a computed property that is derived from it are passed through an event, the former keeps its reactivity while the latter loses it.

An object variable (an Array is an object) contains a reference (or handle) to the object. When you assign one object variable to another, the handle is copied, and both variables are handles to one object. Object operations on one will be "seen" by the other.

So after

foo = [1];
bar = foo;
foo.push(2);

both foo and bar, since they refer to the same object, would be [1, 2]. Passing values works the same way, but it's easier to illustrate with simple assignments.

It should be clear that

foo = [1];
bar = foo;
foo = [1, 2];

assigns a new handle to foo, so it no longer references the same array that bar does.

In your example, arrComputed creates a new Array object every time arrData changes. So when you pass arrComputed, you are passing the handle it created the last time it ran. When arrData changes, arrComputed creates a new Array object, but the recipient of the old handle doesn't get that, and the Array associated with its handle is never updated.



来源:https://stackoverflow.com/questions/49283457/difference-between-computed-property-and-normal-data-in-vue-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!