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 相关文章推荐
图片轮换效果实现代码(点击按钮停止执行)
Apr 12 Javascript
jQuery通过Ajax返回JSON数据
Apr 28 Javascript
angularjs自定义ng-model标签的属性
Jan 21 Javascript
js获取当前年月日-YYYYmmDD格式的实现代码
Jun 01 Javascript
js实现简易垂直滚动条
Feb 22 Javascript
vue2的todolist入门小项目的详细解析
May 11 Javascript
Angular4学习笔记之实现绑定和分包
Aug 01 Javascript
微信小程序中使用Promise进行异步流程处理的实例详解
Aug 17 Javascript
分析JS中this引发的bug
Dec 12 Javascript
JS中数据结构之栈
Jan 01 Javascript
vue源码nextTick使用及原理解析
Aug 13 Javascript
JavaScript实现前端倒计时效果
Feb 09 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中$this-&amp;gt;含义分析
2009/11/29 PHP
ecshop 批量上传(加入自定义属性)
2012/03/20 PHP
PHP开发中csrf攻击的简单演示和防范
2017/05/07 PHP
PHP利用Mysql锁解决高并发的方法
2018/09/04 PHP
JavaScript 应用类库代码
2008/06/02 Javascript
JQuery浮动DIV提示信息并自动隐藏的代码
2010/08/29 Javascript
jquery实现商品拖动选择效果代码(自写)
2013/05/28 Javascript
js简易namespace管理器 实例代码
2013/06/21 Javascript
分析了一下JQuery中的extend方法实现原理
2015/02/27 Javascript
Jquery判断form表单数据是否变化
2016/03/30 Javascript
JavaScript必知必会(七)js对象继承
2016/06/08 Javascript
Ajax异步文件上传与NodeJS express服务端处理
2017/04/01 NodeJs
angularjs路由传值$routeParams详解
2020/09/05 Javascript
详解node nvm进行node多版本管理
2017/10/21 Javascript
浅谈mint-ui 填坑之路
2017/11/06 Javascript
详解JavaScript中关于this指向的4种情况
2019/04/18 Javascript
Node.JS用纯JavaScript生成图片或滑块式验证码功能
2019/09/12 Javascript
vue项目或网页上实现文字转换成语音播放功能
2020/06/09 Javascript
vue+高德地图实现地图搜索及点击定位操作
2020/09/09 Javascript
基于ajax实现上传图片代码示例解析
2020/12/03 Javascript
[54:58]完美世界DOTA2联赛PWL S2 LBZS vs Rebirth 第一场 11.25
2020/11/25 DOTA
Python连接数据库学习之DB-API详解
2017/02/07 Python
PyQt5每天必学之工具提示功能
2018/04/19 Python
Django中使用Whoosh进行全文检索的方法
2019/03/31 Python
IntelliJ 中配置 Anaconda的过程图解
2020/06/01 Python
django models里数据表插入数据id自增操作
2020/07/15 Python
Python利用matplotlib绘制散点图的新手教程
2020/11/05 Python
使用CSS3和Checkbox实现JQuery的一些效果
2015/08/03 HTML / CSS
HTML5调用手机发短信和打电话功能
2020/04/29 HTML / CSS
大学生自我评价范文分享
2014/02/21 职场文书
学校政风行风自查自纠报告
2014/10/21 职场文书
入党积极分子群众意见
2015/06/01 职场文书
反腐倡廉学习心得体会范文
2015/08/15 职场文书
《吸血鬼幸存者》新内容发布 追加多个全新模式
2022/04/07 其他游戏
Python+Pillow+Pytesseract实现验证码识别
2022/05/11 Python
教你win10系统中APPCRASH事件问题解决方法
2022/07/15 数码科技