假设我有一些类的实例,可以通过方法调用进行内部修改(可以添加一些道具,删除一些道具等)。 我怎么能通知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/
有什么干净的方法可以解决吗?
答案 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());
}
}
})