vue用Object.defineProperty手寫一個簡單的雙向綁定的示例
前言 上次寫了一個Object.defineProperty() 不詳解,文末說要寫用它來寫個雙向綁定。說話算話,說來就來
前文鏈接 Object.defineProperty() 不詳解
先看最后效果

model演示.gif
什么是雙向綁定?
1.當(dāng)一個對象(或變量)的屬性改變,那么調(diào)用這個屬性的地方顯示也應(yīng)該改變,模型到視圖(model => view)
2.當(dāng)調(diào)用屬性的這個地方改變了這個屬性(通常是一個表單元素),那么這個對象(或變量)的屬性也會改為最新的值 ,即視圖到模型(view => model)
我們怎么知道對象的屬性變了?
上文說到,Object.defineProperty 設(shè)置對象屬性的描述字段里面有兩個屬性 set (設(shè)置屬性時被調(diào)用)和get(獲取屬性時被調(diào)用),只說不練,你再講什么?眼見為實好嗎?OK ,上代碼
var user = {};
var defaultName = "狂奔的蝸牛";
Object.defineProperty(user,"name",{
get:function(){
console.log("你是不是來獲取值啦");
return defaultName;
},
set:function(value){
console.log("你是不是來設(shè)置值啦");
defaultName = value;
}
})
console.log(user.name);
user.name = "狂奔的蘿卜";
console.log(user.name);

get和set存取時被調(diào)用
如上圖所示 每當(dāng)我獲取user.name屬性時,get方法被調(diào)用,get 方法對應(yīng)的函數(shù)被執(zhí)行,輸出 你是不是來獲取值啦;每當(dāng)我設(shè)置user.name屬性時,set方法對應(yīng)的函數(shù)被執(zhí)行,輸出 你是不是來設(shè)置值啦 ; 是的,我們監(jiān)控到了代碼對user.name屬性的存取。
說明 假設(shè)id="model" 的元素的 value 是user.name的值,既然我們可以在改變屬性的執(zhí)行日志輸出(console.log("你是不是來設(shè)置值啦");),那么,我們在設(shè)置值的時候給id="model" 的元素設(shè)置下新值,不就實現(xiàn)了從模型到視圖???!,說干就干
模型到視圖(model => view)的同步
說明 假設(shè)id="model" 的元素的 value 是user.name的值,既然我們可以在改變屬性的執(zhí)行日志輸出(console.log("你是不是來設(shè)置值啦");),那么,我們在設(shè)置值的時候給id="model" 的元素設(shè)置下新值,不就實現(xiàn)了從模型到視圖?!!,說干就干
<body>
手寫一個簡單雙向綁定<br/>
<input type="text" id="model"><br/>
<div id="modelText"></div>
</body>
<script>
var user = {};
var defaultName = "狂奔的蝸牛";
document.querySelector("#model").value = defaultName;
document.querySelector("#modelText").textContent = defaultName;
//定義屬性 監(jiān)控改變
Object.defineProperty(user,"name",{
get:function(){
console.log("你是不是來獲取值啦");
return defaultName;
},
set:function(newValue){
console.log("設(shè)置新值");
defaultName = newValue;
console.log("實現(xiàn) 模型 => 視圖");
document.querySelector("#model").value = newValue;
document.querySelector("#modelText").textContent = newValue;
}
})
console.log("2s 后改變值");
setTimeout(() => {
//改變值
user.name = "狂奔的蘿卜";
}, 2000);
</script>

模型到視圖(model => view)的同步
視圖到模型(view => model)的同步
問: 我們能捕捉到view對值更改嗎?
答:可以?。?id="model" 的input元素的 value 是user.name的值,填充在這個文本框里面,文本框有個“ keyup” 事件,當(dāng)我們在文本框中輸入文字的時候,文本框的值會跟著改變,并且會連續(xù)觸發(fā)keyup事件,那么我們只需要監(jiān)聽這個事件,是不是就可以捕捉到view對值的更改了??既然文本框的值會跟著改變,我們獲取最新的值再把新值更新到user.name屬性,不就實現(xiàn)了視圖到模型(view => model)的同步?沒代碼說個啥
<body>
手寫一個簡單雙向綁定<br/>
<input type="text" id="model"><br/>
<div id="modelText"></div>
</body>
<script>
var user = {};
var defaultName = "狂奔的蝸牛";
var model = document.querySelector("#model");
var modelText = document.querySelector("#modelText");
model.value = defaultName;
modelText.textContent = defaultName;
//定義屬性 監(jiān)控改變
Object.defineProperty(user,"name",{
get:function(){
console.log("你是不是來獲取值啦");
return defaultName;
},
set:function(newValue){
console.log("設(shè)置新值");
defaultName = newValue;
model.value = newValue;
modelText.textContent = newValue;
}
})
model.addEventListener("keyup", function () {
user.name = this.value;
console.log("實現(xiàn) 視圖 => 模型");
}, false)
</script>

view2model.gif
【最終源碼】
在上述代碼的基礎(chǔ)上,加入了 用戶輸入中文的判斷(用戶輸入中文時,頻繁觸發(fā) keyup事件,但實際上輸入并沒有結(jié)束。)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>雙向綁定</title>
</head>
<body>
手寫一個簡單雙向綁定<br/>
<input type="text" id="model"><br/>
<div id="modelText"></div>
</body>
<script>
var model = document.querySelector("#model");
var modelText = document.querySelector("#modelText");
var defaultName = "defaultName";
var userInfo = {}
model.value = defaultName;
Object.defineProperty(userInfo, "name", {
get: function () {
return defaultName;
},
set: function (value) {
defaultName = value;
model.value = value;
console.log("-----value");
console.log(value);
modelText.textContent = value;
}
})
userInfo.name = "new value";
var isEnd = true;
model.addEventListener("keyup", function () {
if (isEnd) {
userInfo.name = this.value;
}
}, false)
//加入監(jiān)聽中文輸入事件
model.addEventListener("compositionstart", function () {
console.log("開始輸入中文");
isEnd = false;
})
model.addEventListener("compositionend", function () {
isEnd = true;
console.log("結(jié)束輸入中文");
})
</script>
</html>
【完結(jié)】
Object.defineProperty 可以做很多好玩兒的,自己慢慢探索哈~
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
利用Vue3和element-plus實現(xiàn)圖片上傳組件
element-plus提供了uploader組件,但是不好定制化。所以本文將利用Vue3和element-plus實現(xiàn)一個圖片上傳的組件,感興趣的可以了解一下2022-03-03
vue使用ArcGis?API?for?js創(chuàng)建地圖實現(xiàn)示例
這篇文章主要為大家介紹了vue使用ArcGis?API?for?js創(chuàng)建地圖實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08
前端框架Vue父子組件數(shù)據(jù)雙向綁定的實現(xiàn)
Vue項目中經(jīng)常使用到組件之間的數(shù)值傳遞,實現(xiàn)的方法很多,但是原理上基本大同小異。這篇文章將給大家介紹Vue 父子組件數(shù)據(jù)單向綁定與Vue 父子組件數(shù)據(jù)雙向綁定的對比從而認識雙向綁定2021-09-09
ant design vue中table表格滾動加載實現(xiàn)思路
在處理一寫數(shù)據(jù)量特別大的情況下,我們不能把后端的數(shù)據(jù)一次性全部拿到前端在table表格中展示,為了考慮性能優(yōu)化,使用了滾動加載表格數(shù)據(jù),這篇文章主要介紹了ant design vue中table表格滾動加載實現(xiàn)思路,需要的朋友可以參考下2024-07-07
如何將iconfont圖標(biāo)引入到vant的Tabbar標(biāo)簽欄里邊
這篇文章主要介紹了如何將iconfont圖標(biāo)引入到vant的Tabbar標(biāo)簽欄里邊,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04
vue 解決uglifyjs-webpack-plugin打包出現(xiàn)報錯的問題
這篇文章主要介紹了vue 解決uglifyjs-webpack-plugin打包出現(xiàn)報錯的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
使用Vue3實現(xiàn)倒計時器及倒計時任務(wù)的完整代碼
文章介紹了如何使用Vue3和Element-plus開發(fā)一個倒計時器和倒計時任務(wù)管理界面,倒計時器具備手動設(shè)置、開始、暫停和重啟功能,文章還提供了倒計時器的完整代碼,包括HTML、JavaScript和CSS部分,感興趣的朋友一起看看吧2024-11-11
vue3+element-plus動態(tài)路由菜單示例代碼
這篇文章主要介紹了vue3+element-plus動態(tài)路由菜單示例代碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-11-11

