由于 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>
这里也是可以渲染出来的