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 相关文章推荐
TopList标签和JavaScript结合两例
Aug 12 Javascript
让GoogleCode的SVN下的HTML文件在FireFox下正常显示.
May 25 Javascript
jQuery总体架构的理解分析
Mar 07 Javascript
js中取得变量绝对值的方法
Jan 03 Javascript
JavaScript判断对象是否为数组
Dec 22 Javascript
js老生常谈之this,constructor ,prototype全面解析
Apr 05 Javascript
Bootstrap表单控件学习使用
Mar 07 Javascript
微信小程序 跳转方式总结
Apr 20 Javascript
使用live-server快速搭建本地服务器+自动刷新的方法
Mar 09 Javascript
jQuery中将json数据显示到页面表格的方法
May 27 jQuery
VueJs里利用CryptoJs实现加密及解密的方法示例
Apr 29 Javascript
JS学习笔记之数组去重实现方法小结
May 29 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 编写安全的代码时容易犯的错误小结
2010/05/20 PHP
php的urlencode()URL编码函数浅析
2011/08/09 PHP
PHP学习笔记(二):变量详解
2015/04/17 PHP
Symfony生成二维码的方法
2016/02/04 PHP
Zend Framework实现多文件上传功能实例
2016/03/21 PHP
使用jQuery向asp.net Mvc传递复杂json数据-ModelBinder篇
2010/05/07 Javascript
jQuery EasyUI API 中文文档 - Dialog对话框
2011/11/15 Javascript
jquery.post用法之type设置问题
2014/02/24 Javascript
jQuery中html()方法用法实例
2014/12/25 Javascript
小心!AngularJS结合RequireJS做文件合并压缩的那些坑
2016/01/09 Javascript
Jquery zTree 树控件异步加载操作
2016/02/25 Javascript
Immutable 在 JavaScript 中的应用
2016/05/02 Javascript
正则表达式,替换所有HTML标签的简单实例
2016/11/28 Javascript
Vue2.0+ElementUI实现表格翻页的实例
2017/10/23 Javascript
vue组件中使用iframe元素的示例代码
2017/12/13 Javascript
vue父组件点击触发子组件事件的实例讲解
2018/02/08 Javascript
JavaScript实现tab栏切换效果
2020/03/16 Javascript
Vue组件为什么data必须是一个函数
2020/06/11 Javascript
vue-router之解决addRoutes使用遇到的坑
2020/07/19 Javascript
[53:10]完美世界DOTA2联赛决赛日 FTD vs GXR 第二场 11.08
2020/11/11 DOTA
python实现批量图片格式转换
2020/06/16 Python
Pandas_cum累积计算和rolling滚动计算的用法详解
2019/07/04 Python
python数据类型之间怎么转换技巧分享
2019/08/20 Python
Python协程操作之gevent(yield阻塞,greenlet),协程实现多任务(有规律的交替协作执行)用法详解
2019/10/14 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
python模拟实现分发扑克牌
2020/04/22 Python
Python调用shell cmd方法代码示例解析
2020/06/18 Python
C#里面如何倒序排列一个数组的元素?
2013/06/21 面试题
护理学应聘自荐书范文
2014/02/05 职场文书
遗产继承公证书
2014/04/09 职场文书
2014年初中班主任工作总结
2014/11/08 职场文书
Django如何与Ajax交互
2021/04/29 Python
十个Python自动化常用操作,即拿即用
2021/05/10 Python
python pygame入门教程
2021/06/01 Python
MySQL8.0的WITH查询详情
2021/08/30 MySQL
Python实现Excel文件的合并(以新冠疫情数据为例)
2022/03/20 Python