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 相关文章推荐
删除重复数据的算法
Nov 23 Javascript
js实现的动画导航菜单效果代码
Sep 10 Javascript
Boostrap入门准备之border box
May 09 Javascript
手机Web APP如何实现分享多平台功能
Aug 19 Javascript
关于Node.js的events.EventEmitter用法介绍
Apr 01 Javascript
微信小程序 动态传参实例详解
Apr 27 Javascript
vue+swiper实现组件化开发的实例代码
Oct 26 Javascript
微信小程序实现签到功能
Oct 31 Javascript
JavaScript实现随机五位数验证码
Sep 27 Javascript
云服务器部署Node.js项目的方法步骤(小白系列)
Mar 23 Javascript
webpack3.0升级4.0的方法步骤
Apr 02 Javascript
vue 实现tab切换保持数据状态
Jul 21 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实现插入排序?
2013/04/10 PHP
php实现批量下载百度云盘文件例子分享
2014/04/10 PHP
使用PHPMailer实现邮件发送代码分享
2014/10/23 PHP
php组合排序简单实现方法
2016/10/15 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
2018/06/16 PHP
一个小型js框架myJSFrame附API使用帮助
2008/06/28 Javascript
判断JavaScript对象是否可用的最正确方法分析
2008/10/03 Javascript
JavaScript学习笔记(十七)js 优化
2010/02/04 Javascript
JavaScript判断一个URL链接是否有效的实现方法
2011/10/08 Javascript
jQuery实现鼠标滑过遮罩并高亮显示效果
2013/07/16 Javascript
javascript静态页面传值的三种方法分享
2013/11/12 Javascript
jquery 提示信息显示后自动消失的具体实现
2013/12/18 Javascript
jQuery的promise与deferred对象在异步回调中的作用
2016/05/03 Javascript
第五篇Bootstrap 排版
2016/06/21 Javascript
AngularJS 入门教程之HTML DOM实例详解
2016/07/28 Javascript
JS作用域闭包、预解释和this关键字综合实例解析
2016/12/16 Javascript
Angularjs为ng-click事件传递参数
2017/06/15 Javascript
[02:36]DOTA2上海特锦赛 回忆电竞生涯的重要瞬间
2016/03/25 DOTA
[02:04]2018DOTA2亚洲邀请赛Secret赛前采访
2018/04/03 DOTA
[57:22]完美世界DOTA2联赛PWL S2 FTD vs PXG 第二场 11.27
2020/12/01 DOTA
python 动态加载的实现方法
2017/12/22 Python
python使用ddt过程中遇到的问题及解决方案【推荐】
2018/10/29 Python
Python提取支付宝和微信支付二维码的示例代码
2019/02/15 Python
django 信号调度机制详解
2019/07/19 Python
python对Excel按条件进行内容补充(推荐)
2019/11/24 Python
基于opencv的selenium滑动验证码的实现
2020/07/24 Python
python与idea的集成的实现
2020/11/20 Python
html5的自定义data-*属性与jquery的data()方法的使用
2014/07/02 HTML / CSS
遮罩层 + Iframe实现界面自动显示的示例代码
2020/04/26 HTML / CSS
Fnac西班牙官网:法国文化和电子产品零售商
2021/03/14 全球购物
面试自我评价范文
2014/09/17 职场文书
支教个人总结
2015/03/04 职场文书
结婚司仪主持词
2015/06/29 职场文书
python基于opencv批量生成验证码的示例
2021/04/28 Python
WebRTC记录音视频流(web技术分享)
2022/02/24 Javascript
面试提问mysql一张表到底能存多少数据
2022/03/13 MySQL