Original link:Make a big tree
In a project I recently participated in, the vue.js framework was used in the front end. During this period, there was a The function requiresdynamicto add properties to a bound object. However, in practical applications, a problem arises: after adding attributes to the object, the content of the component bound to the object does not change. The component must be refreshed again before its content changes to the changed content.
At first I thought the attribute was not added successfully, because in my impressionv-modelis two-way binding and will not be in a non-updated state. After I checked the monitoring in Devtools, I found that the corresponding object did have the specified attributes added.
So, I went to check the official documents and found the official explanation:How Vue.js tracks changes
When you pass an ordinary JavaScript object into a Vue instance as
dataoption, Vue will traverse all properties of this object and useObject.definePropertyto convert all these properties intogetter/setter.Object.definePropertyis a feature in ES5 that cannot be shimmed, which is why Vue does not support IE8 and lower browsers.Each component instance corresponds to awatcherinstance, which will record the "touched" data properties as dependencies during the component rendering process.Later, when the dependency's setter is triggered, the watcherwill be notified, causing its associated component to re-render.
Due to JavaScript limitations, Vuecannot detect changes toarrays and objects. Still, there are ways to get around these limitations and keep them responsive.
Vue cannot detect the addition or removal of properties. Since Vue will perform getter/setter conversion on the property when initializing the instance, the property must exist on thedataobject in order for Vue to convert it to reactive. For example:
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应式的
vm.b = 2
// `vm.b` 是非响应式的
For already created instances, Vue does not allow dynamic addition of root-level reactive properties. However, you can add reactive properties to nested objects using theVue.set(object, propertyName, value)method. For example, for:
Vue.set(vm.someObject, 'b', 2)
You can also use thevm.$setinstance method, which is also an alias for the globalVue.setmethod:
this.$set(this.someObject,'b',2)
Sometimes you may need to assign multiple new properties to existing objects, such as usingObject.assign()or_.extend(). However, new properties added to the object in this way will not trigger an update. In this case, you should create a new object with the properties of the original object and the object you want to mix in.
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
This is a solution to object assignment. After adopting the official solutionthis.$set(object, key, value), the real-time update effect is indeed achieved. At the same time, for arrays and other situations, you can check theremaining official documents
As the official said"Due to JavaScript limitations, Vuecannot detect changes toarrays and objects.", but why What will happen?
借用 SegmentfaultUKer的回答:
ECMAScript中有两种属性:数据属性和访问器属性; 数据属性的描述符为:Configurable,Enumerable,Writable,Value; 访问器属性的描述符为:Configurable, Enumerable,set,get。
当我们使用new Vue(obj),其内部发生了大体如下代码的转换,即,将数据属性转换为了访问器属性
function Vue(obj){
obj.data.keys().forEach((prop, index) => {
Object.defineProperty(obj.data, prop, {
set(){
//可以在此处进行事件监听
},
get(){
}
})
})
return obj;
}
但是当我们后面再次使用普通的赋值,仅仅是赋值了一个数据属性的,这个属性是不会具有访问器属性的事件监听功能的。
至此,v-model绑定数据不实时更新的问题方才得到了解决。
The above is the detailed content of [Vue] v-model bound objects are not updated in real time. For more information, please follow other related articles on the PHP Chinese website!