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 相关文章推荐
基于prototype的validation.js发布2.3.4新版本,让你彻底脱离表单验证的烦恼
Dec 06 Javascript
经典海量jQuery插件 大家可以收藏一下
Feb 07 Javascript
jquery 利用show和hidden实现级联菜单示例代码
Aug 09 Javascript
Javascript 函数parseInt()转换时出现bug问题
May 20 Javascript
javascript模拟实现ajax加载框实例
Oct 15 Javascript
jquery增加和删除元素的方法
Jan 14 Javascript
超漂亮的jQuery图片轮播特效
Nov 24 Javascript
微信公众号  提示:Unauthorized API function 问题解决方法
Dec 05 Javascript
详解Angular2表单-模板驱动的表单(Template-Driven Forms)
Aug 04 Javascript
node.js文件上传重命名以及移动位置的示例代码
Jan 19 Javascript
javascript canvas时钟模拟器
Jul 13 Javascript
详解vue中v-for的key唯一性
May 15 Vue.js
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
一个域名查询的程序
2006/10/09 PHP
php+mysql大量用户登录解决方案分析
2014/12/29 PHP
PHP实现的简单sha1加密功能示例
2017/08/27 PHP
YII框架页面缓存操作示例
2019/04/29 PHP
使用composer命令加载vendor中的第三方类库 的方法
2019/07/09 PHP
HTML代码中标签的全部属性 中文注释说明
2009/03/26 Javascript
JQuery 实现的页面滚动时浮动窗口控件
2009/07/10 Javascript
用js脚本控制asp.net下treeview的NodeCheck的实现代码
2010/03/02 Javascript
jquery获取css中的选择器(实例讲解)
2013/12/02 Javascript
js获取鼠标点击的位置实现思路及代码
2014/05/09 Javascript
javascript中的遍历for in 以及with的用法
2014/12/22 Javascript
JavaScript闭包详解
2015/02/02 Javascript
node.js调用C++开发的模块实例
2015/07/03 Javascript
bootstrap下拉列表与输入框组结合的样式调整
2016/10/08 Javascript
JavaScript中return用法示例
2016/11/29 Javascript
简单实现JS计算器功能
2016/12/21 Javascript
微信小程序开发探究
2016/12/27 Javascript
详解使用JS如何制作简单的ASCII图与单极图
2017/03/31 Javascript
Vue单页应用引用单独的样式文件的两种方式
2018/03/30 Javascript
原生JS实现图片懒加载之页面性能优化
2019/04/26 Javascript
[02:01]BBC DOTA2国际邀请赛每日综述:八强胜者组鏖战,中国队喜忧参半
2014/07/19 DOTA
python实现探测socket和web服务示例
2014/03/28 Python
Python中Random和Math模块学习笔记
2015/05/18 Python
在Python的Django框架中编写错误提示页面
2015/07/22 Python
Python操作mysql数据库实现增删查改功能的方法
2018/01/15 Python
python人民币小写转大写辅助工具
2018/06/20 Python
解决Keras 与 Tensorflow 版本之间的兼容性问题
2020/02/07 Python
PyCharm+Pipenv虚拟环境开发和依赖管理的教程详解
2020/04/16 Python
python 发送get请求接口详解
2020/11/17 Python
Contém1g官网:巴西彩妆品牌
2020/01/17 全球购物
三爱活动实施方案
2014/03/19 职场文书
中学生励志演讲稿
2014/04/26 职场文书
作风整顿个人剖析材料
2014/10/06 职场文书
2014年人事专员工作总结
2014/11/19 职场文书
承兑汇票延期证明
2015/06/23 职场文书
Django使用channels + websocket打造在线聊天室
2021/05/20 Python