vue用Object.defineProperty手寫一個簡單的雙向綁定的示例
前言 上次寫了一個Object.defineProperty() 不詳解,文末說要寫用它來寫個雙向綁定。說話算話,說來就來
前文鏈接 Object.defineProperty() 不詳解
先看最后效果
model演示.gif
什么是雙向綁定?
1.當一個對象(或變量)的屬性改變,那么調用這個屬性的地方顯示也應該改變,模型到視圖(model => view)
2.當調用屬性的這個地方改變了這個屬性(通常是一個表單元素),那么這個對象(或變量)的屬性也會改為最新的值 ,即視圖到模型(view => model)
我們怎么知道對象的屬性變了?
上文說到,Object.defineProperty 設置對象屬性的描述字段里面有兩個屬性 set (設置屬性時被調用)和get(獲取屬性時被調用)
,只說不練,你再講什么?眼見為實好嗎?OK ,上代碼
var user = {}; var defaultName = "狂奔的蝸牛"; Object.defineProperty(user,"name",{ get:function(){ console.log("你是不是來獲取值啦"); return defaultName; }, set:function(value){ console.log("你是不是來設置值啦"); defaultName = value; } }) console.log(user.name); user.name = "狂奔的蘿卜"; console.log(user.name);
get和set存取時被調用
如上圖所示 每當我獲取user.name屬性時,get方法被調用,get 方法對應的函數被執(zhí)行,輸出 你是不是來獲取值啦;每當我設置user.name屬性時,set方法對應的函數被執(zhí)行,輸出 你是不是來設置值啦 ; 是的,我們監(jiān)控到了代碼對user.name屬性的存取。
說明 假設id="model" 的元素的 value 是user.name的值,既然我們可以在改變屬性的執(zhí)行日志輸出(console.log("你是不是來設置值啦");),那么,我們在設置值的時候給id="model" 的元素設置下新值,不就實現了從模型到視圖?!!,說干就干
模型到視圖(model => view)的同步
說明 假設id="model" 的元素的 value 是user.name的值,既然我們可以在改變屬性的執(zhí)行日志輸出(console.log("你是不是來設置值啦");),那么,我們在設置值的時候給id="model" 的元素設置下新值,不就實現了從模型到視圖???!,說干就干
<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("設置新值"); defaultName = newValue; console.log("實現 模型 => 視圖"); 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” 事件,當我們在文本框中輸入文字的時候,文本框的值會跟著改變,并且會連續(xù)觸發(fā)keyup事件,那么我們只需要監(jiān)聽這個事件,是不是就可以捕捉到view對值的更改了??既然文本框的值會跟著改變,我們獲取最新的值再把新值更新到user.name屬性,不就實現了視圖到模型(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("設置新值"); defaultName = newValue; model.value = newValue; modelText.textContent = newValue; } }) model.addEventListener("keyup", function () { user.name = this.value; console.log("實現 視圖 => 模型"); }, false) </script>
view2model.gif
【最終源碼】
在上述代碼的基礎上,加入了 用戶輸入中文的判斷(用戶輸入中文時,頻繁觸發(fā) keyup事件,但實際上輸入并沒有結束。)
<!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("結束輸入中文"); }) </script> </html>
【完結】
Object.defineProperty 可以做很多好玩兒的,自己慢慢探索哈~
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
vue3 拖拽hooks(可兼容移動端)和自定義指令拖拽的實現代碼
這篇文章主要介紹了vue3 拖拽hooks(可兼容移動端)和自定義指令拖拽的實現代碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考借鑒價值,需要的朋友參考下吧2024-01-01vue3+vite動態(tài)加載路由,本地路由和線上路由匹配方式
這篇文章主要介紹了vue3+vite動態(tài)加載路由,本地路由和線上路由匹配方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06Vue過濾器,生命周期函數和vue-resource簡單介紹
這篇文章主要介紹了Vue過濾器,生命周期函數和vue-resource簡單介紹,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下2021-01-01Vue實現無限輪播效果時動態(tài)綁定style失效的解決方法
最近在開發(fā)中遇到了一個新需求:列表輪播滾動,實現方式也有很多,比如使用第三方插件,但是由于不想依賴第三方插件,想自己實現,于是我開始了嘗試,但是在這個過程中遇到了動態(tài)綁定style樣式不生效,所以本文介紹了Vue實現無限輪播效果時動態(tài)綁定style失效的解決方法2024-08-08