Vue.set — 看完这个就会用了。

时间:2021-1-8 作者:admin

Vue.set :修改数据,并触发视图更新。

BTW : $set是绑定在Vue原型上的set方法,两者并无二致。

因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = 'hi') ,即无法检测到数组,对象的值修改,从而导致页面无法显示实时的数据。

如何使用Vue.set ?

Vue.set( target, propertyName/index, value )
let arr = [1,2,3];
this.set(arr,1,'修改arr数组的第二位数据')

more Play --------------------------------------我是分割线
data:{
  arr: [1,12,34,5,1],
                user: [
                    {name: 'Sean', age: 20},
                    {name: 'Zan', age: 3}
                ],
                userInfo:{
                    name: 'Billy'
                }
}
//1\. 将arr数组中索引为1的值修改为'zan'
Vue.set(this.arr, 1, 'zan'),
//2\. 给user数组添加对象
Vue.set(this.user, 2, {name: 'Billy', age: 10}),
//3\. 修改user数组索引为0的对象属性值
Vue.set(this.user, 0, {name: 'Jim', age: 42}),
//4\. 给对象添加属性
 Vue.set(this.userInfo, 'age', 29)

啥时候需要用到set方法呢?

修改数据后,并没有触发视图更新。就应该考虑使用这个。

Vue在初始实例时进行数据绑定,使用了Object.defineProperty()绑定getter和setter,即此时的data中数据进行了双向绑定。那么如果要添加新的属性,便不是响应式。会导致数据变化,页面不变的情况。

使用了set方法后即做了双向绑定。解决上述问题。

尝试解析 Vue.set的原理:

(部分代码,来源于网络)

注释纯手写,各位看官不妨看一看~。

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)}`)
  }
  // 数组
  // Vue封装过的数组7个方法,push splice等等才会触发页面渲染,这里使用了splice直接触发页面渲染。
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return val
  }
  // 对象
  // 假设key本身就是对象的某个属性,修改既可。例如本身就是data中的属性,修改,会直接触发页面渲染。
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
// 在vue中,如果某个对象存在__ob__属性,那么说明这个对象是响应式的。
// 如此我们在这里进行__ob__属性的判断是否存在,如果存在,那么说明当前对象是响应式的,修改数据,页面会直接进行渲染。
 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
 }
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。