原型继承的属性在vue.js中不起作用吗?

时间:2018-09-20 13:56:00

标签: javascript vue.js

我有这个代码。它纯粹是出于实验目的:

test.html

<div id="example-1">
    {{ stuff.dosobject.notlist }}
    <button v-on:click="dostuff">DO STUFF</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="test.js"></script>

test.js

var oneobject={
        dosobject:{
            notlist:"foo"  
        }
    }

var stuff = Object.create(oneobject)

var example1 = new Vue({
  el: '#example-1',
  data: {
    stuff:stuff
  },
  methods:
  {
      dostuff:function(event)
      {
          if(stuff.dosobject.notlist=="foo")
              stuff.dosobject.notlist="bar"
          else
              stuff.dosobject.notlist="foo"
      }
  }
})

对象stuff是用oneobject作为原型创建的。 我希望属性stuff.dosobject.notlist是反应性的,即单击按钮时将重新渲染模板的{{ stuff.dosobject.notlist }}部分。

似乎并非如此。

我做错什么了吗?还是正常的VueJS行为?

考虑了一下之后,似乎并没有使所有原型属性都具有响应性,这似乎并不奇怪,因为原型链可能会很长,并会导致性能问题。

1 个答案:

答案 0 :(得分:0)

通常,解决这些类型的反应性警告的方法是使用Vue.set

向反应对象添加属性,确保新属性为 还具有反应性,因此触发视图更新。这必须用于添加新 属性,因为Vue无法检测到正常属性 添加内容(例如this.myObject.newProperty = 'hi')。

但是,Vue.set包含以下检查:

https://github.com/vuejs/vue/blob/4f81b5db9ab553ca0abe0706ac55ceb861344330/src/core/observer/index.js#L212-L215

if (key in target && !(key in Object.prototype)) {
 target[key] = val
 return val
}

我已阅读并重新阅读Reactivity in Depth,其中指出:

当您将普通 JavaScript对象传递给Vue实例...(重点是我)

因此,很明显,您不应该传递复杂的对象并且期望反应性起作用。但是,原型继承是“普通”对象的一部分,当您使用类,第三方库或大型,复杂的代码库时,有时不可避免地要处理作为道具或数据传递的“非普通”对象。

通过使用Vue.set“使反应性”现有对象很好,但是由于进行了in检查,它不会将原型值复制到对象并设置反应性吸气剂/设定剂对。

您可以尝试以下两种解决方案:

  1. 克隆对象而不是从对象继承,以确保stuff具有dosobject作为own property

  2. stuff上设置任何属性时触发$forceUpdate,或为stuff创建proxy以在set陷阱中自动执行


在遇到的极端情况下,我们设置了一个函数以确保我们设置的更改被Vue的反应系统吸收:

function setPropertyReactive(obj, key, value) {
  if (obj.hasOwnProperty(key)) {
    obj[key] = value;
    return;
  }

  delete Object.getPrototypeOf(obj)[key];
  Vue.set(obj, key, value);
}