#上代码(原生js实现Vue数据双向绑定)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue数据双向绑定原理</title>
</head>
<body>
<p></p>
<input type="text">
<script>
const obj = {
_temp: ''
}
Object.defineProperty(obj,'msg',{
// obj.msg 获取的时候会触发 get 方法
get(){
// console.log('读了')
// 当你用 obj.msg 获取数据的时候,就会触发 get ,而get 方法里面返回的就是obj._temp,
// 所以就能实现视图的变化影响到 obj.msg 的变化了
return this._temp
},
// obj.msg 赋值的时候,会触发 set 方法,set 方法里面第一个参数就是等号右边的值
set(newValue){
// console.log('写了' + newValue)
// 每次写入的数据时候,都会把最终的结果给 obj._temp
obj._temp = newValue
// #2 M => V
// 做一个数据影响视图的操作
oP.innerHTML = newValue
oInput.value = newValue
}
})
const oP = document.querySelector('p')
const oInput = document.querySelector('input')
// #1 V => M
// 当在 input 框中输入内容会触发事件
oInput.oninput = function(e){
// 这是核心 当 inptu 的 value 改变就触发 obj.msg里的 set方法
obj.msg = e.target.value
}
</script>
</body>
</html>
Object.defineProperty
它接受三个参数,而且都是必填的
传入参数
- 第一个参数:目标对象
- 第二个参数:需要定义的属性或方法的名字。
- 第三个参数:目标属性所拥有的特性。(descriptor)
前两个参数不多说了,一看代码就懂,主要看第三个参数descriptor,看看有哪些取值
descriptor
- configurable: 仅当该属性的 configurable 为 true 时,该属性才能够被改变,也能够被删除。默认为 false
- enumerable: 仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false
- value: 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined
- writable: 仅当仅当该属性的writable为 true 时,该属性才能被赋值运算符改变。默认为 false
- get: 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。undefined
- set: 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为undefined。
descriptor默认值
var a= {}
Object.defineProperty(a,"b",{
value:123
})
console.log(a.b);//123
会默认帮我们把writable,configurable,enumerable。都设上值,而且值还都是false
var a= {}
Object.defineProperty(a,"b",{
value:123,
writable:false,
enumerable:false,
configurable:false
})
console.log(a.b);//123
上面代码和下面是等价的的( 仅限于第一次设置的时候)
configurable
总开关,第一次设置 false 之后,第二次什么设置也不行了
如果第一次不设置它会帮你设置为false
它的默认值为 false
那第二次再设置他会报错
var a= {}
Object.defineProperty(a,"b",{
configurable:false
})
Object.defineProperty(a,"b",{
configurable:true
})
//error: Uncaught TypeError: Cannot redefine property: b
writable
false 是只读
var a = {};
Object.defineProperty(a, "b", {
value : 123,
writable : false });
console.log(a.b); // 打印 37
a.b = 25; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值)
console.log(a.b); // 打印 37, 赋值不起作用。
enumerable
属性特性 enumerable 定义了对象的属性是否可以在 for…in 循环和 Object.keys() 中被枚举。
var o = {};
Object.defineProperty(o, "a", { value : 1, enumerable:true });
Object.defineProperty(o, "b", { value : 2, enumerable:false });
Object.defineProperty(o, "c", { value : 3 }); // enumerable defaults to false
o.d = 4; // 如果使用直接赋值的方式创建对象的属性,则这个属性的enumerable为truefor (var i in o) {
console.log(i);
}
// 打印 'a' 和 'd' (in undefined order)Object.keys(o); // ["a", "d"]
o.propertyIsEnumerable('a'); // true
o.propertyIsEnumerable('b'); // false
o.propertyIsEnumerable('c'); // false
参考:https://blog.csdn.net/m0_51022093/article/details/111597001 & https://juejin.cn/post/6844903506743148552