Vue.js 中计算属性和普通数据的区别 [英] Difference between computed property and normal data in Vue.js

查看:29
本文介绍了Vue.js 中计算属性和普通数据的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我观察到,当来自 data() 的正常属性和从它派生的计算属性通过事件传递时,前者保持其反应性,而后者失去它.

我为它设置了以下测试用例(也作为 JSFiddle 如果你更喜欢):

const EventBus = new Vue();Vue.component('comp', {数据() {返回 {arrData: ['a', 'b']};},计算:{arrComputed() {返回 this.arrData.map((e) => e.toUpperCase());}},模板:`<div><div>原始数组:{{ arrData }}</div><div>计算数组:{{ arrComputed }}</div><button @click="remove('a')">删除一个</button><button @click="remove('b')">移除 b</button><button @click="pass">传递事件</button><button @click="reset">重新开始软</button><button @click="resetHard">重新开始</button></div>`,方法: {删除(名称){name = name.toLowerCase();if(this.arrData.indexOf(name) != -1) {this.$delete(this.arrData, this.arrData.indexOf(name));}},经过() {EventBus.$emit('pass', this.arrData, this.arrComputed);},重启() {this.$set(this.arrData, 0, 'a');this.$set(this.arrData, 1, 'b');},重置硬(){this.arrData = ['a','b'];}}});Vue.component('othercomp', {数据() {返回 {项目 1: [],项目2:[]}},安装(){EventBus.$on('pass', this.receive);},模板:`<div><div>原始数组:{{items1}}</div><div>计算数组:{{items2}}</div></div>`,方法: {接收(项目1,项目2){this.items1 = items1;this.items2 = items2;}}});var app = new Vue({el: '#app',组件:['comp','othercomp']})

<script src="//unpkg.com/vue@latest/dist/vue.js"></script><div id="应用程序"><comp></comp><othercomp></othercomp>

计算与正常属性有何不同,从而导致这种行为差异?

我从上一个问题中了解到,像这样传递反应性对象是不好的做法,我应该使用 getter函数,但我仍然想知道为什么会出现这种差异.

解决方案

我观察到当一个来自 data() 的普通属性和一个从它派生的计算属性通过事件传递,前者保持反应性,后者失去反应性.

对象变量(数组是对象)包含对对象的引用(或句柄).当您将一个对象变量分配给另一个对象时,句柄被复制,并且两个变量都是一个对象的句柄.一个对象的操作会被另一个看到".

之后

foo = [1];酒吧 = foo;foo.push(2);

foobar因为它们指的是同一个对象,所以都是 [1, 2].传递值的工作方式相同,但用简单的赋值更容易说明.

应该很清楚

foo = [1];酒吧 = foo;foo = [1, 2];

foo 分配一个新句柄,因此它不再引用与 bar 相同的数组.

在您的示例中,每次 arrData 更改时,arrComputed 都会创建一个新的 Array 对象.因此,当您传递 arrComputed 时,您传递的是它上次运行时创建的句柄.当 arrData 改变时,arrComputed 会创建一个新的 Array 对象,但旧句柄的接收者没有得到它,并且与其句柄关联的 Array 永远不会更新.

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.

解决方案

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.

这篇关于Vue.js 中计算属性和普通数据的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆