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 相关文章推荐
JS实多级联动下拉菜单类,简单实现省市区联动菜单!
May 03 Javascript
javascript入门·动态的时钟,显示完整的一些方法,新年倒计时
Oct 01 Javascript
FireFox JavaScript全局Event对象
Jun 14 Javascript
javascript管中窥豹 形参与实参浅析
Dec 17 Javascript
js实现简单的可切换选项卡效果
Apr 10 Javascript
HTML页面,测试JS对C函数的调用简单实例
Aug 09 Javascript
原生javascript实现读写CSS样式的方法详解
Feb 20 Javascript
详解Vue使用命令行搭建单页面应用
May 24 Javascript
React-router v4 路由配置方法小结
Aug 08 Javascript
详解Angular如何正确的操作DOM
Jul 06 Javascript
JavaScript中交换值的10种方法总结
Aug 18 Javascript
js canvas实现俄罗斯方块
Oct 11 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&amp;mysql(一)
2006/10/09 PHP
PHP base64+gzinflate压缩编码和解码代码
2008/10/03 PHP
谷歌音乐搜索栏的提示功能php修正代码
2011/05/09 PHP
PHP对表单提交特殊字符的过滤和处理方法汇总
2014/02/18 PHP
PHP实现上传多图即时显示与即时删除的方法
2017/05/09 PHP
用js计算页面执行时间的函数
2006/12/07 Javascript
一个高效的JavaScript压缩工具下载集合
2007/03/06 Javascript
javascript调试过程中找不到哪里出错的可能原因
2013/12/16 Javascript
js中replace的用法总结
2013/12/27 Javascript
jQuery获取和设置表单元素的方法
2014/02/14 Javascript
Nodejs全栈框架StrongLoop推荐
2014/11/09 NodeJs
EasyUI闪屏EasyUI页面加载提示(原理+代码+效果图)
2016/02/21 Javascript
详解Vue.js动态绑定class
2016/12/20 Javascript
JS实现点击Radio动态更新table数据
2017/07/18 Javascript
javaScript实现滚动条事件详解
2020/03/24 Javascript
微信小程序组件传值图示过程详解
2019/07/31 Javascript
微信小程序 弹窗输入组件的实现解析
2019/08/12 Javascript
Python中常用操作字符串的函数与方法总结
2016/02/04 Python
Python编写一个闹钟功能
2017/07/11 Python
使用pygame模块编写贪吃蛇的实例讲解
2018/02/05 Python
Flask框架URL管理操作示例【基于@app.route】
2018/07/23 Python
python随机在一张图像上截取任意大小图片的方法
2019/01/24 Python
pandas dataframe添加表格框线输出的方法
2019/02/08 Python
python的turtle库使用详解
2019/05/10 Python
Python使用get_text()方法从大段html中提取文本的实例
2019/08/27 Python
阿联酋团购网站:Groupon阿联酋
2016/10/14 全球购物
澳大利亚人信任的清洁平台,您的私人管家:Jarvis
2020/12/25 全球购物
单位办理社保介绍信
2014/01/10 职场文书
函授药学自我鉴定
2014/02/07 职场文书
旅游与环境专业求职信
2014/06/05 职场文书
南京市纪委监察局整改方案
2014/09/16 职场文书
党员“四风”方面存在问题及整改措施
2014/09/24 职场文书
作弊检讨书
2015/01/27 职场文书
英文诗歌翻译方法(赏析)
2019/08/16 职场文书
Python内置的数据类型及使用方法
2022/04/13 Python
java高级用法JNA强大的Memory和Pointer
2022/04/19 Java/Android