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 相关文章推荐
JSON.parse 解析字符串出错的解决方法
Jul 08 Javascript
JQuery 选择器、过滤器介绍
Feb 14 Javascript
Notify - 基于jquery的消息通知插件
Oct 18 Javascript
JavaScript中“+”的陷阱深刻理解
Dec 04 Javascript
Jquery获取复选框被选中值的简单方法
Jul 04 Javascript
jquery固定底网站底部菜单效果
Aug 13 Javascript
JAVASCRIPT函数作用域和提前声明 分享
Aug 22 Javascript
html5 canvas js(数字时钟)实例代码
Dec 23 Javascript
JavaScript 常见安全漏洞和自动化检测技术
Aug 21 Javascript
jQuery EasyUI API 中文帮助文档和扩展实例
Aug 01 Javascript
详解vue跨组件通信的几种方法
Jun 15 Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
Sep 03 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 8小时时间差的解决方法小结
2009/12/22 PHP
yii框架源码分析之创建controller代码
2011/06/28 PHP
zf框架的session会话周期及次数限制使用示例
2014/03/13 PHP
Linux中用PHP判断程序运行状态的2个方法
2014/05/04 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
2017/08/30 PHP
php判断/计算闰年的方法小结【三种方法】
2019/07/06 PHP
用JS实现一个页面多个css样式实现
2008/05/29 Javascript
Jquery Autocomplete 结合asp.net使用要点
2010/10/29 Javascript
JavaScript操作XML 使用百度RSS作为新闻源示例
2012/02/17 Javascript
javascript学习笔记(十八) 获得页面中的元素代码
2012/06/20 Javascript
点弹代码 点击页面任何位置都可以弹出页面效果代码
2012/09/17 Javascript
Knockout visible绑定使用方法
2013/11/15 Javascript
JS数组的赋值介绍
2014/03/10 Javascript
浅析webapp框架AngularUI的demo
2014/12/21 Javascript
浅谈javascript的Touch事件
2015/09/27 Javascript
jQuery实现商品活动倒计时
2015/10/16 Javascript
微信小程序组件之srcoll-view的详解
2017/10/19 Javascript
基于jQuery中ajax的相关方法汇总(必看篇)
2017/11/08 jQuery
利用Node.js检测端口是否被占用的方法
2017/12/07 Javascript
基于Vue实现可以拖拽的树形表格实例详解
2018/10/18 Javascript
layui实现tab的添加拒绝重复的方法
2019/09/04 Javascript
vue实现动态表格提交参数动态生成控件的操作
2020/11/09 Javascript
[19:26]TNC vs EG (BO3)
2018/06/07 DOTA
在Python中使用zlib模块进行数据压缩的教程
2015/06/26 Python
详解MySQL数据类型int(M)中M的含义
2016/11/20 Python
利用Python如何将数据写到CSV文件中
2018/06/05 Python
django的csrf实现过程详解
2019/07/26 Python
Tkinter中复选菜单是否被选中的判断与设置方式
2020/03/04 Python
详解通过变换矩阵实现canvas的缩放功能
2019/01/14 HTML / CSS
Pamela Love官网:纽约设计师Pamela Love的精美、时尚和穿孔珠宝
2020/10/19 全球购物
证券期货行业个人的自我评价
2013/12/26 职场文书
电子信息科学专业自荐信
2014/01/30 职场文书
大学生第一学年自我鉴定2015
2014/09/28 职场文书
刑事和解协议书范本
2014/11/19 职场文书
房地产公司财务总监岗位职责
2015/04/03 职场文书
高二英语教学反思
2016/03/03 职场文书