Vue进阶(九十八):Vue.set()和this.$set()介绍

举报
SHQ5785 发表于 2020/12/29 23:07:32 2020/12/29
【摘要】 场景 有时候我们会看到如下代码: 在我们使用vue进行开发的过程中,可能会遇到一种情况:当生成vue实例后,当再次给对象赋值时,有时候并不会自动更新到视图上去; 当我们去看vue文档的时候,会发现有这么一句话:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。 如下代码,给 student对象新增 age 属性。 data () { return {...

场景

有时候我们会看到如下代码:
在这里插入图片描述
在我们使用vue进行开发的过程中,可能会遇到一种情况:当生成vue实例后,当再次给对象赋值时,有时候并不会自动更新到视图上去; 当我们去看vue文档的时候,会发现有这么一句话:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。 如下代码,给 student对象新增 age 属性。

data () {
  return { student: { name: '', sex: '' }
  }
}
mounted () { // ——钩子函数,实例挂载之后
  this.student.age = 24
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除,即Vue未做到脏数据检查。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。
正确写法:this.$set(this.data,”key”,value')

mounted () {
  this.$set(this.student,"age", 24)
}

  
 
  • 1
  • 2
  • 3

Vue 不允许动态添加根级响应式属性。

例如:

const app = new Vue({
  data: { a: 1
  }
  // render: h => h(Suduko)
}).$mount('#app1')

Vue.set(app.data, 'b', 2)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

此时控制台会报错:
在这里插入图片描述
只可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性,例如

var vm=new Vue({ el:'#test', data:{ //data中已经存在info根属性 info:{ name:'小明'; } }
});
//给info添加一个性别属性
Vue.set(vm.info,'sex','男');

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

有童鞋可能会问之前使用过Vue.set(),this.$set()Vue.set有什么联系呢?

Vue.set()和this.$set()实现原理

源码分析
我们先来看看Vue.set()的源码:

import { set } from '../observer/index'

...
Vue.set = set
...

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

再来看看this.$set()的源码:

import { set } from '../observer/index'

...
Vue.prototype.$set = set
...

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

我们发现Vue.set()和this.$set()这两个api的实现原理基本一模一样,都是使用了set函数。set函数是从 …/observer/index 文件中导出的,区别在于Vue.set()是将set函数绑定在Vue构造函数上,this.$set()是将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)}`)
  }
  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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

我们发现set函数接收三个参数分别为 target、key、val,其中target的值为数组或者对象,这正好和官网给出的调用Vue.set()方法时传入的参数参数对应上。
在这里插入图片描述

文章来源: shq5785.blog.csdn.net,作者:No Silver Bullet,版权归原作者所有,如需转载,请联系作者。

原文链接:shq5785.blog.csdn.net/article/details/104570686

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。