Vue2.X 雙向數據綁定使用的是 Object.defineProperty(),Vue3 使用的是 Proxy。
Object.defineProperty()
Object.defineProperty(obj, prop, descriptor)
obj要定義屬性的對象。
prop要定義或修改的屬性的名稱或 Symbol 。
descriptor要定義或修改的屬性描述符。
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<input class="inp-text" type="text">
<div class="text-box"></div>
</body>
<script>
let obj = {};
Object.defineProperty(obj, 'name', {
set: function(newValue){
console.log('觸發(fā)setter');
document.querySelector('.text-box').innerHTML = newValue;
document.querySelector('.inp-text').value = newValue;
},
get: function(){
console.log('觸發(fā)getter');
}
});
document.querySelector('.inp-text').addEventListener('input', function(e){
obj.name = e.target.value;
}, false);
</script>
</html>
Proxy
const p = new Proxy(target, handler)
target要使用Proxy包裝的目標對象(可以是任何類型的對象,包括原生數組,函數,甚至另一個代理)。
handler一個通常以函數作為屬性的對象,各屬性中的函數分別定義了在執(zhí)行各種操作時代理p的行為。
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="div1">
<input type="text" v-model="name"><br>
姓名:{{name}}<br>
年齡:{{age}}
</div>
</body>
<script>
let el=document.getElementById('div1');
let template=el.innerHTML;
let _data={
name: 'liangzai',
age: 18
};
let data=new Proxy(_data, {
set(obj, name, value){
//alert(`有人視圖設置 ${name}=>${value}`);
obj[name]=value;
//數據變了
//console.log('數據變了');
render();
}
});
render();
function render(){
//渲染
el.innerHTML=template.replace(/\{\{\w+\}\}/g, str=>{
str=str.substring(2, str.length-2);
return _data[str];
});
//找所有的v-model
Array.from(el.getElementsByTagName('input'))
.filter(ele=>ele.getAttribute('v-model'))
.forEach(input=>{
let name=input.getAttribute('v-model');
input.value=_data[name];
input.oninput=function (){
console.log(1)
data[name]=this.value;
};
});
}
</script>
</html>