1、ES6 的 getter 、setter 和 Object.defineProperty
- getter
- 使用 getter 后,obj1.姓名 就是一个属性,而不再是方法
- 示例:
let obj1 = {
姓:'w',
名:'bh',
姓名(){
return this.姓 + this.名
}
}
console.log(obj1.姓名())
//使用 getter
let obj2 = {
姓:'w',
名:'bh',
get 姓名(){
return this.姓 + this.名
}
}
console.log(obj2.姓名) //输出:wbh
- setter
- 不能使用 obj3.姓名('高媛媛'),因为 obj3.姓名 并不是一个方法函数,而是用 set 模拟的属性
- 示例:
let obj3 = {
姓:'w',
名:'bh',
get 姓名(){
return this.姓 + this.名
}
set 姓名(xxx){
this.姓 = xxx[0]
this.名 = xxx.substring(1)
}
}
obj3.姓名 = '高原源'
console.log(`姓:${obj.姓},名:${obj.名}`) //输出:姓:高,名:原源
2、Object.defineProperty()
Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。- 语法:
Object.defineProperty(obj, prop, descriptor)- obj:要在其上定义属性的对象。
- prop:要定义或修改的属性的名称。
- descriptor:将被定义或修改的属性描述符。
- 示例:
const object1 = {};
Object.defineProperty(object1, 'property1', {
value: 42,
});
console.log(object1.property) //输出:42
Object.defineProperty的作用:- 可以给对象添加属性 value,可以给对象添加 getter/setter
- getter / setter 用于对属性的读写进行监控
3、对于代理和监听的理解
- 代理:让 data3 成为 {n:0} 的代理,通过 data3 访问 n 就会转变为对 obj 的操纵,访问 obj 的n,通过 data3 设定一个 n,就是设定 obj 对象中的 n。
- 示例:
let data3 = proxy({ data:{n:0} })
function proxy({data}){
// function proxy(options){
// const data = options.data => const {data} = options
const obj = {}
Object.defineProperty(obj, 'n', {
get(){
return data.n
},
set(value){
if(value<0)return
data.n = value
}
})
return obj // obj 就是代理
}
data3.n = -1
console.log(`${data3.n}`) //输出:0
- 监听:就是通过
Object.defineProperty方法把原来的 mayData5 删除并覆盖,从而确保用户无法直接的修改 mayData5 中的内容 - 示例:
let myData5 = {n:0}
let data5 = proxy2({ data:myData5 }) /
function proxy2({data}){
let value = data.n
Object.defineProperty(data, 'n', {
get(){
return value
},
set(newValue){
if(newValue<0)return
value = newValue
}
})
...
}
4、关于new Vue()对 data 做了什么?
const vm = new Vue({data: myData})- vue 会让 vm 成为 myData 的代理。
- vue 会对 myData 的所有属性进行监控。
- 可以使用 this 来访问到 vm。 this.n === myData.n。
- 之所以要监控,就是防止 vue 无法得知 myData 的属性变化。
- vue 得知属性变化才可以使用 render(data) 来更新 UI 和渲染页面。
- 只要传入一个 myData,原来的 n 就会被改为 get n() 和 set n(value)

5、数据响应式
- const vm = new Vue({data:{n: 0}})
- 当修改 vm.n 或 data.n 时,render(data...) 中的 n 就会做出响应的响应。
- 这个联动的过程就是 vue 的 数据响应式。
- vue 目前通过 Object.defineProperty 来实现数据响应式。
- 但是,如果操作原来不存在 data 中的属性呢?
- 示例:
new Vue({
data: {
obj: {
a: 0 // obj.a 会被 Vue 监听 & 代理
}
},
template: `
<div>
{{obj.b}}
<button @click="setB">set b</button>
</div>
`,
methods: {
setB() {
this.obj.b = 1; //不会显示出 1
}
}
}).$mount("#app");
-
Vue 没法监听一开始就不存在的 obj.b
-
解决方法:
- 提前声明好 obj.b
data: { obj: { a: 0, // obj.a 会被 Vue 监听 & 代理 b:undefined } },2.使用 Vue.set 或者 this.$set
Vue.set(this.obj, "b", 1); this.$set(this.obj,'b',1) // 二选一 -
关于 vue.set 和 this.$set
-
作用:
- 新增 key
- 自动创建代理和监听(如果没有创建过)
- 触发 UI 更新(并不会立刻更新)
6、data 中有数组怎么办?
- 由于数组本身的特性,长度无法预估,因此你没法提前声明所有的 key
- 数组的长度可以一直增加,下标就是 key
- 因此无法提前给每一个 key 都设定为 undefined,或是每一个都使用 Vue.set 来设置,但是要注意的是 Vue.set 作用于数组时,并不会自动添加监听和代理
- 解决方法:
- 使用 Vue 对数组的变更方法:
push()pop()shift()unshift()splice()sort()reverse()
- 这些方法 (API) 会自动处理对数组该项的监听和代理,并触发视图更新。
- 原理就是声明一个新的类来继承数组的原本方法
- 使用 Vue 对数组的变更方法:
7、个人对 Vue 的数据响应式的理解
- 当对 Vue 新增一个 data 数据时,通过
Object.defineProperty方法,将其中的所有属性转化为 setter 和 getter ,从而对其 data 的改变进行监听 - 再把 vm 作为 data 的代理,对 data 进行监控,vm 在监听到变化后会调用
render(data) UI = render(data)