♥ vue中$set用法详细讲解
1、认识
在vue中,并不是任何时候数据都是双向绑定的。
vue2是用object.definedProperty来实现数据响应的,他无法监听深层数据的变化。所以需要使用this.$set来实现数据的修改和添加。如:
`this.$set(this.test, 'text1', 'test');`
而vue3是通过proxy代理来实现数据的响应,通过ref和reactive将值和对象类型变为响应式对象,所以这样对它的修改和添加就能被vue捕获到,从而实现页面的自动刷新。所以直接对对象本身进行修改或者添加就行了,this.$set自然就没用了
const test =reactive({
name: 'test',
temp:'temp',
})
const change=()=>{
test.name='new'
}
const add=()=>{
test.test="add"
}
const dels=()=>{
delete test.temp
}
$set是Vue.js中用于为响应式对象添加属性的实例方法,可以在运行时向响应式对象添加新的响应式属性,并确保这些属性也是响应式的。
在Vue.js中, s e t 是用于向响应式对象添加新属性的方法,可以实现动态添加属性和修改数组元素等操作,能够确保这些属性也是响应式的。需要注意的是, set是用于向响应式对象添加新属性的方法,可以实现动态添加属性和修改数组元素等操作,能够确保这些属性也是响应式的。需要注意的是, set是用于向响应式对象添加新属性的方法,可以实现动态添加属性和修改数组元素等操作,能够确保这些属性也是响应式的。需要注意的是,set不能用于向根数据添加属性,而且不能在computed计算属性中使用
$set接收三个参数:对象、属性名和属性值
// 添加响应式属性 vue2
this.$set(对象,'属性名',属性值);
// 添加响应式属性 vue3
const obj = reactive({
a: 1
})
$set(obj, 'b', 2)
官方文档介绍
使用场景
当数据没有被双向绑定的时候,我们就需要使用set了`
举个例子:
vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的。
2、$set作用和用法
(1)解决动态添加属性不响应的问题
在Vue.js中,如果在实例化后的响应式对象中添加新属性,则该新属性默认不会是响应式的,也就是说,如果这个属性的值发生变化,页面不会随之更新。
不生效代码案例
export default {
data() {
return {
obj: { a: 1 }
}
},
methods: {
addProp() {
this.obj.b = 2
}
}
}
调用addProp方法添加属性b后,页面不会响应更新,需要用$set来解决该问题
$set的解决方法
import { $set } from 'vue'
this.$set(this.obj, 'b', 2)
(2) 动态修改数组
不生效代码案例
通过改变数组元素的值和指定下标添加元素并不能触发视图更新,可以使用$set来解决该问题
export default {
data() {
return {
arr: [1, 2, 3]
}
},
methods: {
change() {
// 修改数组元素的值
this.arr[0] = 4
// 添加新元素到数组
this.arr[3] = 4
// 输出数组长度
console.log(this.arr.length)
}
}
}
$set的解决方法
import { $set } from 'vue'
this.$set(this.arr, 0, 4) // 参数1为数组,参数2为下标,参数3为修改后的值
this.$set(this.arr, 3, 4)
console.log(this.arr.length) // 输出4
数据没有被双向绑定我们可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名
- this.$set(原数组, 索引值, 需要赋的值)
length的问题还需要用splice方法
- vm.items.splice(newLength)
set为解决双向绑定失效,所以什么时候双向绑定失效就用它
当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
由于 JavaScript 的限制,Vue不能检测对象属性的添加或删除
var vm= new Vue({
data: {
a: 1
}
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的
vm.a是响应式的, vm.b不是响应式的
简单来说
对象中原来有这个key=> 双向绑定
对象中原来没有这个key,新增的key=>不是双向绑定
vm.$set(con.userProfile, 'age', 27)
进一步使用
如果我们添加的属性很多条,可能就需要写一个循环来多次set
你也可能使用Object.assign,这里有一些需要注意的地方。
如果你想添加新的响应式属性,下面这样写是不行的。
Object.assign(vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
这样才是正确的
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
3、$set的使用注意事项
(1)对于引用类型的对象,需要递归添加属性
如果要添加的属性是一个引用对象或嵌套引用对象的属性,需要使用递归方式将添加操作完成:
// 示例代码
const obj = reactive({
a: {
b: 1
}
})
// 递归添加响应式属性
$set(obj.a, 'c', 2)
( 2 ) 不能向根数据添加属性
不能使用$set添加到Vue实例根数据的属性,因为这些属性在创建Vue实例时就已经初始化,无法做到响应式处理
// 示例代码
const vm = createApp({
data() {
return {
a: 1
}
},
created() {
// $set添加到根数据的属性会报错
this.$set(this, 'b', 2)
}
})
vm.mount('#app')
( 3 )不能在computed中使用$set
computed计算属性的返回值必须是纯函数,不能有副作用。如果在computed中使用$set方法,会破坏这个约束,可能会产生一些无法预测的错误
4、原理
————————————————————————————
Vue2 中的数据响应式是利用 object.definedProperty()实现的,它是无法深层监听数据的变化的
Vue3,利用的是ES6的proxy,对数据响应式进行一个数据的代理。
由于 Vue 会在初始化实例时进行双向数据绑定,使用Object.defineProperty()对属性遍历添加 getter/setter 方法,所以属性必须在 data 对象上存在时才能进行上述过程 ,这样才能让它是响应的。如果要给对象添加新的属性,此时新属性没有进行过上述过程,不是响应式的,所以会出想数据变化,页面不变的情况。此时需要用到$set。
向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property
(比如 this.myObject.newProperty = ‘hi’)
————————————————————————————