Vue2.0 $set()的正确使用详解


Posted in Javascript onJuly 28, 2020

vue2.0 给data对象新增属性,并触发视图更新

如下代码,给 student对象新增 age 属性

data () {
  return {
    student: {
      name: '',
      sex: ''
    }
  }
}

众所周知,直接给student赋值操作,虽然可以新增属性,但是不会触发视图更新

mounted () {
  this.student.age = 24
}

原因是:受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。

要处理这种情况,我们可以使用$set()方法,既可以新增属性,又可以触发视图更新。

但是,值得注意的是,网上一些资料写的$set()用法存在一些问题,导致在新接触这个方法的时候会走一些弯路!

错误写法:this.$set(key,value)(ps: 可能是vue1.0的写法)

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

正确写法:this.$set(this.data,”key”,value')

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

补充知识:Vue 中 $set() 与 Vue.set() 原理及使用

1. 前言

问题: 在使用 vue 进行开发的过程中,可能会遇到一种情况:当生成vue实例后,再次给数据赋值时,有时候并不会自动更新到视图上去。也就是如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。

案例:

<template>
 <div class="home">
  <div v-for="(item,index) in items" :key="index">{{item}}</div>
 <button @click="btn()">修改</button>
 </div>
</template>

<script>
export default {
 name: 'Home',
 data(){
  return{
  items:[1, 2, 3]
   }
 },
 methods:{
 btn(){
     this.items[1] = 'two'
  console.log(this.items);
 }
  }
}
</script>

页面:

Vue2.0 $set()的正确使用详解

控制台:

Vue2.0 $set()的正确使用详解

原因: 受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。

因此: Vue 不能检测以下变动的数组:

当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue

当你修改数组的长度时,例如:vm.items.length = newLength

例如:使用 this.arr[0] 去更新 array 的内容,视图没有刷新

使用 Vue.set(this.arr, 0, !this.arr[0]) 去更新 array 的内容,视图被刷新

使用 this.arr[0] = !this.arr[0] 和 this.obj.a = !this.obj.a 同时更新,视图被刷新

结论:

如果方法里面单纯的更新数组 Array 的话,要使用 Vue.set();

如果方法里面同时有数组和对象的更新,直接操作 data 即可;

2. 原理

每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。

Vue2.0 $set()的正确使用详解

受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

3. $set() 与 Vue.set() 的使用

3.1 通过 Vue.set() 改写

语法:

Vue.set( target, propertyName/index, value )

参数:

{Object | Array} target

{string | number} propertyName/index

{any} value

返回值:设置的值。

用法:

向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。

它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = 'hi')

注意:

对象不能是 Vue 实例,或者 Vue 实例的根数据对象。

<template>
 <div class="home">
  <div v-for="(item,index) in items" :key="index">{{item}}</div>
  <button @click="btn()">修改</button>
 </div>
</template>

<script>
import Vue from 'vue' // 别忘了引入
export default {
 name: 'Home',
 data(){
  return{
  items:[1, 2, 3]
  }
 },
 methods:{
 btn(){
      Vue.set(this.items, 1, 'two')
  console.log(this.items);
 }
 }
}
</script>

3.2 通过 $set() 改写

语法:

vm.$set( target, propertyName/index, value )

参数:

{Object | Array} target

{string | number} propertyName/index

{any} value

返回值:设置的值。

用法:

这是全局 Vue.set 的别名。

参考:Vue.set

<template>
 <div class="home">
  <div v-for="(item,index) in items" :key="index">{{item}}</div>
 <button @click="btn()">修改</button>
 </div>
</template>

<script>
export default {
 name: 'Home',
 data(){
  return{
  items:[1, 2, 3]
   }
 },
 methods:{
 btn(){
    this.$set(this.items, 1, 'two')
  console.log(this.items);
 }
 }
}
</script>

页面:

Vue2.0 $set()的正确使用详解

控制台:

Vue2.0 $set()的正确使用详解

3.3 Vue.set() 和 this.$set() 的区别

Vue.set() 源码:

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

this.$set() 源码

import { set } from '../observer/index'
...
Vue.prototype.$set = set
...

可以发现 Vue.set() 和 this.$set() 这两个 api 的实现原理基本一模一样,都是使用了set函数。

set 函数是从 …/observer/index 文件中导出的。

区别在于 Vue.set( ) 是将 set 函数绑定在 Vue 构造函数上,this.$set() 是将 set 函数绑定在 Vue原型上。

以上这篇Vue2.0 $set()的正确使用详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery 1.3.2 IE8中的一点点的小问题解决方法
Jul 10 Javascript
Ext对基本类型的扩展 ext,extjs,format
Dec 25 Javascript
JavaScript 判断日期格式是否正确的实现代码
Jul 04 Javascript
动态创建script标签实现跨域资源访问的方法介绍
Feb 28 Javascript
JavaScript获取Url里的参数
Dec 18 Javascript
分享十五款 jQuery 社交网络分享插件
May 16 Javascript
详细谈谈AngularJS的子级作用域问题
Sep 05 Javascript
深入了解JavaScript的逻辑运算符(与、或)
Dec 20 Javascript
Three.js的使用及绘制基础3D图形详解
Apr 27 Javascript
layui表格实现代码
May 20 Javascript
vue路由结构可设一层方便动态添加路由操作
Aug 31 Javascript
游戏开发中如何使用CocosCreator进行音效处理
Apr 14 Javascript
JavaScript 监听组合按键思路及代码实现
Jul 28 #Javascript
JavaScript动画实例之粒子文本的实现方法详解
Jul 28 #Javascript
Vue $emit()不能触发父组件方法的原因及解决
Jul 28 #Javascript
vue 遮罩层阻止默认滚动事件操作
Jul 28 #Javascript
JavaScript实现沿五角星形线摆动的小圆实例详解
Jul 28 #Javascript
处理JavaScript值为undefined的7个小技巧
Jul 28 #Javascript
vue中touch和click共存的解决方式
Jul 28 #Javascript
You might like
php 在windows下配置虚拟目录的方法介绍
2013/06/26 PHP
thinkphp实现上一篇与下一篇的方法
2014/12/08 PHP
ThinkPHP提示错误Fatal error: Allowed memory size的解决方法
2015/02/12 PHP
php中memcache 基本操作实例
2015/05/17 PHP
PHP实现QQ空间自动回复说说的方法
2015/12/02 PHP
Jquery下attr和removeAttr的使用方法
2010/12/28 Javascript
Eval and new funciton not the same thing
2012/12/27 Javascript
基于jquery的has()方法以及与find()方法以及filter()方法的区别详解
2013/04/26 Javascript
jQuery实现弹出窗口中切换登录与注册表单
2015/06/05 Javascript
jQuery获取URL请求参数的方法
2015/07/18 Javascript
JS跨域交互(jQuery+php)之jsonp使用心得
2016/07/01 Javascript
Vue计算属性的使用
2017/08/04 Javascript
原生JS实现瀑布流插件
2018/02/06 Javascript
vue.js仿hover效果的实现方法示例
2019/01/28 Javascript
jquery添加div实现消息聊天框
2020/02/08 jQuery
vuex实现购物车功能
2020/06/28 Javascript
JS实现简易日历效果
2021/01/25 Javascript
js动态添加带圆圈序号列表的实例代码
2021/02/18 Javascript
Python实现读取邮箱中的邮件功能示例【含文本及附件】
2017/08/05 Python
解决出现Incorrect integer value: '' for column 'id' at row 1的问题
2017/10/29 Python
Django项目实战之用户头像上传与访问的示例
2018/04/21 Python
浅析python3中的os.path.dirname(__file__)的使用
2018/08/30 Python
Python设计模式之建造者模式实例详解
2019/01/17 Python
导入tensorflow时报错:cannot import name 'abs'的解决
2019/10/10 Python
pycharm实现猜数游戏
2020/12/07 Python
h5网页水印SDK的实现代码示例
2019/02/19 HTML / CSS
世界上最大的家庭自动化公司:Smarthome
2017/12/20 全球购物
会计毕业生自我鉴定
2013/11/04 职场文书
施工班组长岗位职责
2014/01/05 职场文书
房地产项目策划书
2014/02/05 职场文书
综合办公室主任岗位职责
2014/04/13 职场文书
不忘国耻振兴中华演讲稿
2014/05/14 职场文书
走群众路线剖析材料
2014/10/09 职场文书
工作证明格式范文
2015/06/15 职场文书
2019公司管理制度
2019/04/19 职场文书
演讲稿之开卷有益
2019/08/07 职场文书