Vue2.0 $set()的正确使用详解

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>

页面:

控制台:

原因: 受 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 重新计算,从而致使它关联的组件得以更新。

受现代 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>

页面:

控制台:

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()的正确使用详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • vue中 this.$set的用法详解

    当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的. <template> <div id="app"> <p v-for="item in items" :key="item.id">{{item.message}}</p> <button class="btn" @click=&qu

  • vue.js中$set与数组更新方法

    由于 JavaScript 的限制,Vue 不能检测以下变动的数组: 当利用索引直接设置数组的某一项时,例如:vm.items[indexOfItem] = newValue 当你修改数组的长度时,例如:vm.items.length = newLength,不会更新数组. 当然vue中给了解决方法,就是使用 Vue.set, vm.$set(Vue.set的变种写法)或者 splice,caoncat等修改数组,同时也将触发状态更新: ex: 所以如果在实例创建后添加新的属性到实例上,则不会触

  • 深入理解vue中的$set

    在我们使用vue进行开发的过程中,可能会遇到一种情况:当生成vue实例后,当再次给数据赋值时,有时候并不会自动更新到视图上去: 当我们去看vue文档的时候,会发现有这么一句话:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新.如下代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vue $set</title> <scri

  • 从vue源码解析Vue.set()和this.$set()

    前言 最近死磕了一段时间vue源码,想想觉得还是要输出点东西,我们先来从Vue提供的Vue.set()和this.$set()这两个api看看它内部是怎么实现的. Vue.set()和this.$set()应用的场景 平时做项目的时候难免不会对 数组或者对象 进行这样的骚操作操作,结果发现,咦~~,他喵的,怎么页面没有重新渲染. const vueInstance = new Vue({ data: { arr: [1, 2], obj1: { a: 3 } } }); vueInstance.

  • Vue2.0 $set()的正确使用详解

    vue2.0 给data对象新增属性,并触发视图更新 如下代码,给 student对象新增 age 属性 data () { return { student: { name: '', sex: '' } } } 众所周知,直接给student赋值操作,虽然可以新增属性,但是不会触发视图更新 mounted () { this.student.age = 24 } 原因是:受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除.因为 Vue.js 在初始化实例时将属性转为 getter

  • 基于vue2.0动态组件及render详解

    如下所示: <template> <div class="hello"> <h1>{{ msg }}</h1> <h2>这里是Boor</h2> <component v-bind:my-data="items" v-bind:is="currentView"> <!-- 组件在 vm.currentview 变化时改变! --> </compo

  • vue2.0自定义指令示例代码详解

    1.什么是指令? 指令通常以"v-"作为前缀, 以方便Vue知道你在使用一种特殊的标记. 除了 Vue 核心携带着的一些默认指令(v-model 和 v-show)之外, Vue 还允许你注册自己的自定义指令.某些情况下,还是需要对普通元素进行一些底层 DOM 访问, 这也是自定义指令仍然有其使用场景之处. 2.全局指令: 当页面加载时,元素将获取焦点,事实上,在访问页面时,如果你还没有点击任何地方,上面的输入框现在应该处于获取焦点的状态.现在让我们构建指令以完成此效果: <te

  • 对python list 遍历删除的正确方法详解

    在遍历list的时候,删除符合条件的数据,可是总是报异常,代码如下: num_list = [1, 2, 3, 4, 5] print(num_list) for i in range(len(num_list)): if num_list[i] == 2: num_list.pop(i) else: print(num_list[i]) print(num_list) 原因是在删除list中的元素后,list的实际长度变小了,但是循环次数没有减少,依然按照原来list的长度进行遍历,所以会造成

  • mybatis3.4.6 批量更新 foreach 遍历map 的正确姿势详解

    好久没编码了!最近开始编码遇到一个问题 !一个批量修改的问题,就是mybatis foreach 的使用. 当时使用的场景 ,前端 传逗号拼接的字符串id, 修改id对应数据的数据顺序 ,顺序 就是id 的顺序. 就是一个条件(单个id值) 修改一个值(传入的id的顺序) , 1. 把条件作为Map 的key 修改值是value,用map入参 2.用List<Object> 或者数组 ,把条件和值封装成对象放进list集合或者array数组 3.代码使用for循环调用mapper方法 穿两个参

  • 正则表达式中问号(?)的正确用法详解

    目录 1.直接跟随在子表达式后面 2.非贪婪匹配 3.非获取匹配 4.断言 参考资料: 正则表达式中“?”的用法大概有以下几种 1.直接跟随在子表达式后面 这种方式是最常用的用法,具体表示匹配前面的一次或者0次,类似于{0,1},如:abc(d)?可匹配abc和abcd 2.非贪婪匹配 关于贪婪和非贪婪,贪婪匹配的意思是,在同一个匹配项中,尽量匹配更多所搜索的字符,非贪婪则相反.正则匹配的默认模式是贪婪模式,当?号跟在如下限制符后面时,使用非贪婪模式(*,+,?,{n},{n,},{n,m})

  • Vue2 的 diff 算法规则原理详解

    目录 前言 算法规则 diff 优化策略 老数组的开始与新数组的开始 老数组的结尾与新数组的结尾 老数组的开始与新数组的结尾 老数组的结尾与新数组的开始 以上四种情况都没对比成功 推荐在渲染列表时为节点设置 key 循环比对结束的后续处理工作 源码解析 总结 前言 所谓 diff 算法,就是通过比对新旧两个虚拟节点不一样的地方,针对那些不一样的地方进行新增或更新或删除操作.接下来我们详细介绍节点更新的过程. 首先进行静态节点处理,判断新旧两个虚拟节点是否是静态节点,如果是,就不需要进行更新操作,

  • Java BigDecimal正确用法详解

    目录 一.背景 二.事故案例 1.问题 2.问题复现 3.源码分析 4.原因分析 三.总结 四.工具类 一.背景 BigDecimal 平时主要用于计算金钱时,其自身提供了很多的构造方法,但是这些构造方法使用不当会造成精度丢失,从而引起事故. 二.事故案例 1.问题 收银台计算商品价格报错,导致订单无法支付 2.问题复现 public static void main(String[] args) { BigDecimal bigDecimal=new BigDecimal(88); Syste

  • git stash的正确用法详解

    目录 概述 git stash 具体用法 概述 前段时间突然发现,我之前对git stash的使用都是错误的. 具体说来,我是这么使用的:在远端有新的提交,需要git pull来拉取合并时,发现本地有一些未提交的修改,功能也没实现,不适合做一次commit.这时候我执行git stash隐藏本地的修改,然后执行git pull来拉取远端的更新,在最新代码基础上重新实现stash的那些代码中的功能. 这里的问题是,重新实现stash代码中的那一步,其实完全可以用git stash pop来替代,执

  • Vue2如何支持composition API示例详解

    目录 前言 如何使用 原理解析 响应式( ref reactive 的实现) 总结 前言 自从 Vue3 发布之后,composition API 这个词走入写 Vue 同学的视野之中,相信大家也一直听到 composition API 比之前的 options API 有多好多强,如今由于 @vue/composition-api 插件的发布,Vue2 的同学也可以上车咯,接下来我们主要以响应式的 ref 和 reactive 来深入分析一下,这个插件是怎么实现此功能的. 如何使用 // 入口

随机推荐