如面试官问你vue中双向数据绑定实现原理是啥? 一句话其实vue中的v-model 底层就是用到就是 object.defineproperty
然后继续问你object.defineproperty 是 这么使用和自己这么实现一个双向绑定?
然后你可沉默一会。。。。 开始一下的装逼之路
首先 我们看看这这么使用和有哪些属性
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。Object.defineProperty(obj, prop, descriptor)
obj
- 要定义属性的对象。
prop
- 要定义或修改的属性的名称或
Symbol
。 descriptor
- 要定义或修改的属性描述符。
- descriptor 中有那属性注意看:
configurable
- 当且仅当该属性的
configurable
键值为true
时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
默认为false
。 enumerable
- 当且仅当该属性的
enumerable
键值为true
时,该属性才会出现在对象的枚举属性中。
默认为false
。
数据描述符还具有以下可选键值:
value
- 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
默认为undefined
。 writable
- 当且仅当该属性的
writable
键值为true
时,属性的值,也就是上面的value
,才能被赋值运算符
改变。
默认为false
。
存取描述符还具有以下可选键值:
下面是demo ,有助于更好的理解
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Object.defineProperty实现双向绑定</title>
</head>
<body>
<h1 id='h1'></h1>
<input type="text" id="inp" onkeyup="inputChange(event)">
<input type="button" value="加" onclick="btnAdd()" />
</body>
<script>
//数据源
let vm = {
value: 0
}
//用于管理watcher的Dep对象
let Dep = function () {
this.list = [];
this.add = watcher => this.list.push(watcher),
this.notify = newValue => {
this.list.forEach(fn => {
fn(newValue)
})
}
};
// 模拟compile,通过对Html的解析生成一系列订阅者(watcher)
function renderInput(newValue) {
let el = document.getElementById('inp');
if (el) {
el.value = newValue
}
}
function renderTitle(newValue) {
let el = document.getElementById('h1');
if (el) {
el.innerHTML = newValue
}
}
//将解析出来的watcher存入Dep中待用
let dep = new Dep();
dep.add(renderInput);
dep.add(renderTitle)
console.log(dep);
console.log(Dep);
//核心方法
function initMVVM(vm) {
console.log(Object.keys(vm));
Object.keys(vm).forEach(key => {
observer(vm, key, vm[key])
})
}
function observer(vm, key, value) {
Object.defineProperty(vm, key, {
enumerable: true,
configurable: true,
get: function () {
console.log('Get');
return value
},
set: function (newValue) {
if (value !== newValue) {
value = newValue
console.log('Update')
//将变动通知给相关的订阅者
dep.notify(newValue)
}
}
})
}
//页面引用的方法
function inputChange(ev) {
let value = Number.parseInt(ev.target.value);
vm.value = (Number.isNaN(value)) ? 0 : value;
}
function btnAdd() { // 点击添加1
vm.value = vm.value + 1;
}
//初始化数据源
initMVVM(vm)
//初始化页面
dep.notify(vm.value);
</script>
</html>
object.defineProperty中的set和get的区别
1,get和set是方法,因为是方法,所以可以进行判断
2,get是得到,一般是要返回的;set是设置,不用返回
3,如果调用对象内部的属性,约定的命名方式是_age
你学废了吗?