由于 Vue 会在初始化实例时进行双向数据绑定,使用Object.defineProperty()对属性遍历添加 getter/setter 方法,所以属性必须在 data 对象上存在时才能进行上述过程 ,这样才能让它是响应的。如果要给对象添加新的属性,此时新属性没有进行过上述过程,不是响应式的,所以会出想数据变化,页面不变的情况。此时需要用到$set。
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。
例:这里想点击按钮时添加一个新元素,用JavaScript新增元素
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h2>{{person.name}}</h2>
<h2>{{person.age}}</h2>
<h2 v-show="person.sex">{{person.sex}}</h2>
<button @click="add">增加性别</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data(){
return {
person:{
name:'张三',
age:30,
}
}
},
methods: {
add(){
this.person.sex = '女'
console.log(this.person);
}
},
})
</script>
</body>
</html>
这里并不会渲染到浏览器中,只会出现在控制台
对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如,对于:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h2>{{person.name}}</h2>
<h2>{{person.age}}</h2>
<h2 v-show="person.sex">{{person.sex}}</h2>
<button @click="add">增加性别</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data(){
return {
person:{
name:'张三',
age:30,
}
}
},
methods: {
add(){
Vue.set(this.person,'sex','女') //
}
},
})
</script>
</body>
</html>
输出效果:
也可以通过this.$set(object, propertyName, value)实例方法,例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h2>{{person.name}}</h2>
<h2>{{person.age}}</h2>
<h2 v-show="person.sex">{{person.sex}}</h2>
<button @click="add">增加性别</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data() {
return {
person: {
name: '张三',
age: 30,
}
}
},
methods: {
add() {
this.$set(this.person, 'sex', '女')//this.$set(object, propertyName, value)
}
},
})
</script>
</body>
</html>
这里也是可以渲染出来的