在VUE中,有时候我们改变了data里面的数据,但是改变的数据并没有更新到页面上去,但是当我们打印的时候显示确实是更新了已经,只是没有更新到页面上而已,也就是说我们更新的数据没有触发响应式,如下:
<p>{
{
arr}}-{
{
obj}}</p>
data() {
return {
arr:[1],
obj:{
a:1,
b:2,
},
}
this.arr[1]="a" //当然这种方式很少用
this.obj.c=3
console.log(this.arr);
console.log(this.obj);
由此可以看出,当我们主动改变了obj和arr但是页面并不会更新,VUE的官网给我们提供了this.$set
来解决这个问题,我们可以从this.$set()
的源码入手来分析法来发生这个问题的原因:
vue中set的源码
// src/core/observer/index.js
export function set (target: Array<any> | Object, key: any, val: any): any {
if (process.env.NODE_ENV !== 'production' &&
(isUndef(target) || isPrimitive(target))
) {
warn(`Cannot set reactive property on undefined, null, or primitive value: ${
(target: any)}`)
}
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, val)
return val
}
if (key in target && !(key in Object.prototype)) {
target[key] = val
return val
}
const ob = (target: any).__ob__
if (target._isVue || (ob && ob.vmCount)) {
process.env.NODE_ENV !== 'production' && warn(
'Avoid adding reactive properties to a Vue instance or its root $data ' +
'at runtime - declare it upfront in the data option.'
)
return val
}
if (!ob) {
target[key] = val
return val
}
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
1.数组的实现原理(比较直观,容易理解)
在源码中很容易找的处理数组的源码,如下
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, val)
return val
}
2.对象的实现原理