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 工具函数学习资料
Apr 29 Javascript
jQuery.get、jQuery.getJSON、jQuery.post无法返回JSON问题的解决方法
Jul 28 Javascript
javascript自动改变文字大小和颜色的效果的小例子
Aug 02 Javascript
jquery实现盒子下拉效果示例代码
Sep 12 Javascript
jQuery中removeProp()方法用法实例
Jan 05 Javascript
Javascript之面向对象--方法
Dec 02 Javascript
解决JSON.stringify()自动将中文转译成unicode的问题
Jan 05 Javascript
Vue插值、表达式、分隔符、指令知识小结
Oct 12 Javascript
详解微信小程序实现仿微信聊天界面(各种细节处理)
Feb 17 Javascript
node将geojson转shp返回给前端的实现方法
May 29 Javascript
Layui 动态禁止select下拉的例子
Sep 03 Javascript
OpenLayers加载缩放控件使用方法详解
Sep 25 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会员权限控制实现原理分析
2011/05/29 PHP
PHP基于自定义类随机生成姓名的方法示例
2017/08/05 PHP
PHP实现用户异地登录提醒功能的方法【基于thinkPHP框架】
2018/03/15 PHP
Laravel框架实现超简单的分页效果示例
2019/02/08 PHP
深入分析js中的constructor和prototype
2012/04/07 Javascript
js 通用订单代码
2013/12/23 Javascript
javascript引擎长时间独占线程造成卡顿的解决方案
2014/12/03 Javascript
javascript实现的字符串与十六进制表示字符串相互转换方法
2015/07/17 Javascript
谈谈JSON对象和字符串之间的相互转换JSON.stringify(obj)和JSON.parse(string)
2015/10/01 Javascript
Bootstrap导航简单实现代码
2017/03/06 Javascript
react学习笔记之state以及setState的使用
2017/12/07 Javascript
微信小程序实现多个按钮的颜色状态转换
2019/02/15 Javascript
Vue项目部署的实现(阿里云+Nginx代理+PM2)
2019/03/26 Javascript
小程序怎样让wx.navigateBack更好用的方法实现
2019/11/01 Javascript
Python解析nginx日志文件
2015/05/11 Python
python八大排序算法速度实例对比
2017/12/06 Python
python实现简易版计算器
2020/06/22 Python
如何使用Python的Requests包实现模拟登陆
2018/04/27 Python
python中文编码与json中文输出问题详解
2018/08/24 Python
Python 利用scrapy爬虫通过短短50行代码下载整站短视频
2018/10/29 Python
python将处理好的图像保存到指定目录下的方法
2019/01/10 Python
PyQt5内嵌浏览器注入JavaScript脚本实现自动化操作的代码实例
2019/02/13 Python
[机器视觉]使用python自动识别验证码详解
2019/05/16 Python
Django框架自定义模型管理器与元选项用法分析
2019/07/22 Python
django之静态文件 django 2.0 在网页中显示图片的例子
2019/07/28 Python
Spring http服务远程调用实现过程解析
2020/06/11 Python
浅析css3中matrix函数的使用
2016/06/06 HTML / CSS
html5的canvas方法使用指南
2014/12/15 HTML / CSS
美国大城市最热门旅游景点门票:CityPASS
2016/12/16 全球购物
英国领先的男士服装和时尚零售商:Burton
2017/01/09 全球购物
求职意向书范文
2014/04/01 职场文书
2014年党员整改措施
2014/10/24 职场文书
2014年效能监察工作总结
2014/11/21 职场文书
2014年幼儿园班级工作总结
2014/12/17 职场文书
ajax请求前端跨域问题原因及解决方案
2021/10/16 Javascript
Golang 并发编程 SingleFlight模式
2022/04/26 Golang