Vue中Vue.set和this.$set的使用
一.背景vue初始化实例对象的时候会把属性转位setter/getter。这样数据才会是动态响应的(即data中的数据是动态响应的),vue才能监听到属性的添加,删除,修改(受ES5的限制)。二.原理(1)vue.set源码import { set } from '../observer/index'...Vue.set = set...(2)this.$set源码import { set } f
一.背景
vue初始化实例对象的时候会把属性转位setter/getter。这样数据才会是动态响应的(即data中的数据是动态响应的),vue才能监听到属性的添加,删除,修改(受ES5的限制)。
二.原理
(1)vue.set源码
import { set } from '../observer/index'
...
Vue.set = set
...
(2)this.$set源码
import { set } from '../observer/index'
...
Vue.prototype.$set = set
...
三.区别
(1)Vue.set
1.vue.set可以设置实例创建之后添加的新的特性(即在data中未声明,vue实例创建时beforeCreate之后,created之前,监听data对象数据变,并未初始化vue内部事件)
2.vue.set不允许添加根级响应式属性,只可以嵌套对象添加响应式属性
备注:什么是根级响应式属性
由于vue不允许动态添加根级响应式属性,所以你必须在初始化实例前声明根级响应式属性,哪怕只是一个空值:
var vm = new Vue({
data: {
// 声明 message 为一个空值字符串
message: ''
},
template: '<div>{{ message }}</div>'
})
// 之后设置 `message`
vm.message = 'Hello!'
如果你在data属性中未声明message,vue将警告你渲染函数在试图访问的属性不存在
这样的限制在背后是有技术原因的,它消除了在依赖项跟踪系统中的一类边界情况,也是vue实例在类型检查系统的帮助下运行的更高效。而且在代码可维护性方面也有一点考虑:data对象就像组件状态的概要,提前声明所有的响应式属性,可以让组件代码在以后阅读或其他开发人员阅读时更易于理解。
3.vue.set是将set函数绑定在vue构造函数
(2)this.$set
1.this.$set只能设置实例创建后存在的数据(数据已经在data中)
2.将set函数绑定在vue原型上
四.代码
(1)想要在obj对象里面添加C属性
<template>
<div class="">
<input type="text" v-model="obj.a" />
<input type="text" v-model="obj.b" />
<input type="text" v-model="obj.c" />
<hr />
<button @click="fn">点击出现3</button>
</div>
</template>
<script>
export default {
data() {
return {
obj: {
a: 1,
b: 2,
},
};
},
name: "",
methods: {
fn() {
this.obj.c = 3;
},
},
};
</script>
<style scoped></style>
(2)点击完之后的图示
(3)这个时候就可以采用上面介绍的方法
1.代码:
<template>
<div class="">
<input type="text" v-model="obj.a" />
<input type="text" v-model="obj.b" />
<input type="text" v-model="obj.c" />
<hr />
<button @click="fn">点击出现3</button>
</div>
</template>
<script>
export default {
data() {
return {
obj: {
a: 1,
b: 2,
},
};
},
name: "",
methods: {
fn() {
this.$set(this.obj, "c", 3);
},
},
};
</script>
<style scoped></style>
里面用到的方法是:this.$set(第一个参数是要添加的对象,第二个是key(需要要用引号包裹起来),第三个是需要添加的值)
2.图示:
实现了响应式
(3)this的指向问题
打印this出现的结果是:
可以看出打印出来的结果是一个组件的实例,原型链条的查找机制
因此可以访问到this.$set这个方法。
(4)接下来使用Vue.set来实现响应式
1.代码:
<template>
<div class="">
<input type="text" v-model="obj.a" />
<input type="text" v-model="obj.b" />
<input type="text" v-model="obj.c" />
<hr />
<button @click="fn">点击出现3</button>
</div>
</template>
<script>
import Vue from "vue";
export default {
data() {
return {
obj: {
a: 1,
b: 2,
},
};
},
name: "",
methods: {
fn() {
Vue.set(this.obj, "c", 3);
},
},
};
</script>
<style scoped></style>
2.图示:
点击之后:
(5)实现数组的响应式方法
1.数组中的push方法
<template>
<div class="">
<ul>
<li v-for="(item, index) in arr" :key="index">{{ item }}</li>
<hr />
<button @click="fn">点击添加</button>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
arr: ["小红", "小明", "小华"],
};
},
name: "",
methods: {
fn() {
this.arr.push("小蔡");
},
},
};
</script>
<style scoped></style>
2.图示
3.使用上述的两种方法
(1)代码
<template>
<div class="">
<ul>
<li v-for="(item, index) in arr" :key="index">{{ item }}</li>
<hr />
<button @click="fn">点击添加</button>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
arr: ["小红", "小明", "小华"],
};
},
name: "",
methods: {
fn() {
this.$set(this.arr, this.arr.length, "小蔡");
},
},
};
</script>
<style scoped></style>
(2)图示:
(3) this.$set(this.arr, this.arr.length, "小蔡");参数解析 | 与对象的对比 this.$set(this.obj, "c", 3);(可在上方对象的描述进行查找)
this.arr:数组 this.obj:对象
this.arr.length:要添加的索引的位置 "c":对象中的key值
"小蔡":要进行添加的值 3:对象中的value值
(4)使用Vue.set方法
1.代码:
<template>
<div class="">
<ul>
<li v-for="(item, index) in arr" :key="index">{{ item }}</li>
<hr />
<button @click="fn">点击添加</button>
</ul>
</div>
</template>
<script>
import Vue from "vue";
export default {
data() {
return {
arr: ["小红", "小明", "小华"],
};
},
name: "",
methods: {
fn() {
Vue.set(this.arr, this.arr.length, "小蔡");
},
},
};
</script>
<style scoped></style>
2.图示:
3. 区别
1.引入了
import Vue from "vue";
2.而this.$set直接在原型链中进行查找
更多推荐
所有评论(0)