Vue 中 $set() 与 Vue.set() 原理及使用

勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

导读:本篇文章讲解 Vue 中 $set() 与 Vue.set() 原理及使用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1. 前言

问题: 在使用 vue 进行开发的过程中,可能会遇到一种情况:当生成vue实例后,再次给数据赋值时,有时候并不会自动更新到视图上去。也就是 如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。

案例:

<template>
  <div class="home">
    <div>{{student}}</div>
    <div v-for="(item,index) in items" :key="index">{{item}}</div>
	  <button @click="btn()">修改</button>
  </div>
</template>

<script>
export default {
  name: 'Home',
  data(){
    return{
      student:{
        name:'张三',
      },
	  items:[1, 2, 3],
    }
  },
  methods:{
	btn(){
      this.student.age = 18;
      this.items[1] = 'two';
	  console.log(this.student,this.items);
	}
  }
}
</script>

当点击按钮后页面:
在这里插入图片描述

当点击按钮后控制台:
在这里插入图片描述

原因:
受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以 属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。

因此:
Vue 不能检测以下变动的数组:
当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
eg:
使用 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>{{student}}</div>
    <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{
      student:{
        name:'张三',
      },
	  items:[1, 2, 3],
    }
  },
  methods:{
	btn(){
      Vue.set(this.student, 'age', 18);
      Vue.set(this.items, 1, 'two');
	  console.log(this.student,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>{{student}}</div>
    <div v-for="(item,index) in items" :key="index">
      <span>年龄:{{item.age}}</span>
      <span>地点:{{item.address}}</span>
    </div>
	<button @click="btn()">修改</button>
  </div>
</template>

<script>
export default {
  name: 'Home',
  data(){
    return{
      student:{
        name:'张三',
      },
      items:[
        {
          age:12,
          address:'南京',
        },{
          age:15,
          address:'深圳',
        },{
          age:20,
          address:'上海',
        }
      ]
    }
  },
  methods:{
    btn(){
      this.$set(this.student, 'age', 18);
      this.$set(this.items, 1, {age:22, address:'武汉'});
      console.log(this.student,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原型上。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/141434.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!