通知vue项目内部已更改

时间:2018-03-17 15:36:59

标签: vue.js

假设我有一些类的实例,可以通过方法调用进行内部修改(可以添加一些道具,删除一些道具等)。 我怎么能通知vue这些变化(怎么说vue“重新加载这个项目才能被动”)?

感谢。

PS:没有从类中访问vue(假设它是外部库)

以下是https://jsfiddle.net/h34a7s0n/50/

的示例

可能的解决方案:

// Let's say structure of 'item' is changed.
// We have to give some kick to Vue to reinitialize observer
// And yes, we need to know 'item' internals :(

// First remove old observer. 
delete this.item._data.__ob__;

// Next define the new one
Vue.util.defineReactive(this.item.__ob__.value, '_data', this.item._data);

// And finally notify about changes, like $set does
this.item.__ob__.dep.notify();

是的,很脏。但它有效:https://jsfiddle.net/h34a7s0n/89/

有什么干净的方法可以解决吗?

1 个答案:

答案 0 :(得分:0)

问题是v2的{​​{1}}属性。 _data,具体而言,不是被动的。

官方文档 - Change Detection Caveats

  

由于现代JavaScript的限制(以及放弃v2),Vue 无法检测属性添加或删除

要解决它,你可以在构造函数中声明它(当你知道你将拥有什么属性时,这个选项效果最好):

Object.observe

  constructor(v1) {
    this._data = {
      v1,
      v2: null  // <========= added this
    };
  }
class C {
  constructor(v1) {
    this._data = {
      v1,
      v2: null  // <========= added this
    };
  }

  addV2(v2) {
    this._data['v2'] = v2;
    alert( 'Item is fully loaded' );
    console.log(this._data);
  }

  get value1() {
    return this._data.v1;
  }

  get value2() {
    if ('v2' in this._data) {
      return this._data.v2;
    }

    return;
  }
}

new Vue({
  el: '#app',
  template: `
  <div>
     <div>
			{{item.value1}}, {{item.value2}}
			<button @click="fullLoad">+</button>
		</div>
  </div>`,
  data: {
    item: new C(0)
  },
  methods: {
    fullLoad() {
      this.item.addV2(2 * Math.random());
      
      // How to notify vue about changes here?
    }
  }
})

或使用<script src="https://unpkg.com/vue"></script> <div id="app"></div>进行更改。 (此选项最适用于一般情况。)

Vue.set()

  addV2(v2) {
    Vue.set(this._data, 'v2', v2);    // <========= changed here
    alert( 'Item is fully loaded' );
    console.log(this._data);
  }
class C {
  constructor(v1) {
    this._data = {
      v1
    };
  }

  addV2(v2) {
    Vue.set(this._data, 'v2', v2);    // <========= changed here
    alert( 'Item is fully loaded' );
    console.log(this._data);
  }

  get value1() {
    return this._data.v1;
  }

  get value2() {
    if ('v2' in this._data) {
      return this._data.v2;
    }

    return;
  }
}

new Vue({
  el: '#app',
  template: `
  <div>
     <div>
			{{item.value1}}, {{item.value2}}
			<button @click="fullLoad">+</button>
		</div>
  </div>`,
  data: {
    item: new C(0)
  },
  methods: {
    fullLoad() {
      this.item.addV2(2 * Math.random());
      
      // How to notify vue about changes here?
    }
  }
})


无法访问第三方类代码

如果您无法访问<script src="https://unpkg.com/vue"></script> <div id="app"></div>类内部,则可以重新添加C数据属性,如下所示:

item

Runnable demo:

  methods: {
    fullLoad() {
      let i = this.item;                                  // save for reinsertion
      this.item = null;                                   // remove
      Vue.set(this, 'item', i);                           // reinsert as fully reactive

      this.item.addV2(2 * Math.random());
    }
  }
class C {
  constructor(v1) {
    this._data = {
      v1
    };
  }

  addV2(v2) {
    this._data['v2'] = v2;
    alert( 'Item is fully loaded' );
    console.log(this._data);
  }

  get value1() {
    return this._data.v1;
  }

  get value2() {
    if ('v2' in this._data) {
      return this._data.v2;
    }

    return;
  }
}

new Vue({
  el: '#app',
  template: `
  <div>
     <div>
			{{item.value1}}, {{item.value2}}
			<button @click="fullLoad">+</button>
		</div>
  </div>`,
  data: {
    item: new C(0)
  },
  methods: {
    fullLoad() {
      let i = this.item;                                  // save for reinsertion
      this.item = null;                                   // remove
      Vue.set(this, 'item', i);                           // reinsert as fully reactive
      
      this.item.addV2(2 * Math.random());
    }
  }
})