Vue.set()的使用,以及对其进行深入解析
创始人
2024-05-05 06:01:13

目录

Vue.set()使用

Vue.delete()的使用

 Vue.set()方法原理解析

总结

Vue.set()使用

vue 在实例上添加新的属性的时候,该属性,并不是响应式的。同样删除某一属性的时候,也不会实时渲染到页面上。

        比如:

 

年龄:{{obj.age? obj.age: "无"}}

        ···········      

 data() {

            return {        

                obj:{ name:"Lena", id:1 },

            }

          }

页面上 显示的是  年龄:无   现在需要添加一个响应式的属性 age 。


效果:

通过 this.obj.age= 20 ,控制台打印已经有了该属性,并没有渲染到页面上。 可见,这种方式添加的属性 age 并不是响应式的。

使用Vue.set() ,更改add()方法:

add(){Vue.set(this.obj,'age', '20')},

效果:

 因为vue不能检测到对象属性的添加或者删除,只有在data对象上存在的属性是响应式的,所以要使用Vue.set()方法将响应式属性添加到对象上。同样的道理,删除对象 Vue.delete也是如此。

Vue.delete()的使用



效果:

 del() 方法如果是下面两种,同样不是响应式的。

del(){

      delete this.obj.age

    },

或者:

del(){

      this.obj = { name:"Lena", id:1 }

    },

 Vue.set()方法原理解析

        我们找到封装set方法的地方:.........\node_modules\vue\src\core\observer\index.js

 找到封装的set方法:

export function set (target: Array | 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] = valreturn 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] = valreturn val}defineReactive(ob.value, key, val)ob.dep.notify()return val
}

对象调用:Vue.set( target ,'age', 20 ) 

数组调用Vue.set( array , 0,  20 )  //数组对象,索引,值


        首先是判断是否是开发环境并且 对象是否被定义isUndef(target)或者是否是基础类型isPrimitive(target),否则会报错:

`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`

if (process.env.NODE_ENV !== 'production' &&

    (isUndef(target) || isPrimitive(target))

  )


        如果是数组的话,调用重写的splice()方法,可以更新视图。

        isValidArrayIndex(key)方法用来验证是否是一个有效的数组索引, 其实就是验证是否是一个非无穷大的正整数。

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

  }


 如果是Vue实例,或者是根数据data的时候,就会报错。

如果本身就不是响应式的,只需要直接赋值即可。

const ob = (target: any).__ob__//如果是Vue实例,或者是根数据data的时候,就会报错。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] = valreturn val}defineReactive(ob.value, key, val)ob.dep.notify()return val

排除各种不合适的,最后给当前对象定义一个属性:defineReactive(ob.value, key, val) 相当于用了 Object.defineProperty 重新定义了一下。

最后,手动通知视图更新:ob.dep.notify()

总结

这个 set方法,对于数组来说,调用的就是splice,对于对象来说,使用的就是defineReactive,再添加了一个手动的视图更新。这就是set的原理。

相关内容

热门资讯

阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...