Project scenario:
For example: when I was writing a front-end project, the backend gave us a json object, and I had already rendered it on the page. But due to my own needs, I wanted to add a field to the returned object, only to realize that it was not responsive. If we want to make this new field responsive, we need to use this.$set to inject data.
When an object or array is declared or assigned in Vue's data (the value in the array is an object), a new property is added to the object. If the value of this property is updated, the view will not be updated.
Problem Description
Not much to say, let's go to the demo:
<!--先看一个例子-->
<template>
<div class="hello">
<div>{
{
list}}</div>
<button @click="add">age++</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
list: {
name:'LL'}
}
},
methods:{
add(){
if(!this.list.age){
this.list.age=18
}else
{
this.list.age++
}
console.log(this.list)
}
}
}
</script>
<style scoped>
</style>
When we do not use this.$set
to add object properties, the rendering is as follows:
the new property age has indeed been added, but the page list has not been re-rendered to the view layer, and the page does not have a responsive rendering age property
When we use this.$set
to add object properties:
add(){
if(!this.list.age){
// this.list.age=18
this.$set(this.list,'age',18)
}else
{
this.list.age++
}
console.log(this.list)
}
We can find that the data added at this time becomes responsive data.
Cause Analysis:
Since Vue will perform two-way data binding when initializing the instance, and use Object.defineProperty() to add getter/setter methods to property traversal, the above process must be performed when the property exists on the data object, so that it can be responsive. If you want to add a new attribute to the object, the new attribute has not undergone the above process at this time, and it is not responsive, so it will appear that the data changes and the page remains unchanged. At this time, you need to use $set.
Add a property to the reactive object and make sure the new property is also reactive and triggers a view update. It must be used to add new properties to reactive objects, because Vue cannot detect ordinary new properties
(such as this.myObject.newProperty = 'hi')
Vue cannot detect the addition or removal of properties. Since Vue performs getter/setter conversion on the property when initializing the instance, the property must exist on the data object for Vue to convert it to reactive. For example:
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应式的
vm.b = 2
// `vm.b` 是非响应式的
solution:
use:
Vue.set( target, propertyName/index, value )
参数:
{
Object | Array} target
{
string | number} propertyName/index
{
any} value
返回值:设置的值
Array:
this.$set(Array, index, newValue)
Note: The array used here is to modify and replace the value through the index.
Object:
this.$set(Object, 'Key', Value)
Note: The object here is modified and operated by the key name, so it needs to use the sting format.
Replenish:
Sometimes you may need to assign multiple new properties to existing objects, such as using Object.assign() or _.extend(). However, new properties thus added to the object do not trigger updates. In this case, you should create a new object with the original object and the properties of the object to be mixed in.
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({
}, this.someObject, {
a: 1, b: 2 })
For more information, please see the official website Vue Responsive Principle