關於簡單的數據雙向綁定原理,defineProperty 和Proxy演示
雙向綁定,也就是說js中的數據傳到頁面,頁面中的內容到js,實現同步更新,簡單的演示可以直接複製下放HTML程式碼運行。
在這個例子中,我們使用defineProperty ,Object.defineProperty()
方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,並返回此對象。詳細資訊可以自行查看MDN文檔。
簡單來說,defineProperty 就是一個監聽器,監聽對象中某一個屬性被訪問和修改,在Vue2.0中就是採用defineProperty
注意事項
- 在使用get函數監聽屬性的時候,不能直接監聽當前屬性,否則會出現死循環。所以在使用前我將對象進行淺拷貝的原因
- 每一個defineProperty只能對一個對象屬性進行監聽,所以你必須在使用之前就得知道屬性的名字,但是很多時候屬性是動態生成的,,所以就很麻煩。
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1 id="hname"></h1> <input type="text" id="inputname"> </body> <script> let stu = { name: "" } let newstu = { ...stu };//淺拷貝 //監聽器 Object.defineProperty(stu, "name", { get() { return newstu.name; }, set(val) { if (val === newstu.name) return; newstu.name = val; doubleBind(); } }) //將數據傳到頁面中 function doubleBind() { document.querySelector("#hname").innerHTML = stu.name; inputname.value = stu.name;//id可以直接使用 } //輸入框事件,將頁面中數據返回 inputname.oninput = function () { stu.name = inputname.value; } doubleBind() setTimeout(() => { stu.name = "Mary"; }, 1000) </script> </html>
defineProperty的弊端很明顯,在ES6中提出了Proxy, 在Vue3.0中也將使用Proxy代替defineProperty,在Proxy中,我們可以在監聽整一個對象屬性的變化。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1 id="hname"></h1> <input type="text" id="inputname"> </body> <script> let stu = { name: "12354" } //監聽器處理函數 //監聽器 stu = new Proxy(stu, { get(target, prop) { return target[prop]; }, set(target, prop,val){ if (val === target.prop) return; target[prop] = val; doubleBind(); } }); //將數據傳到頁面中 function doubleBind() { document.querySelector("#hname").innerHTML = stu['name']; inputname.value = stu['name'];//id可以直接使用 } //輸入框事件,將頁面中數據返回 inputname.oninput = function () { stu['name'] = inputname.value; } doubleBind() setTimeout(() => { stu['name'] = "Mary"; console.log(stu); }, 1000) </script> </html>
對比兩個例子,眼尖的friend會發現,第一個例子中我訪問對象屬性使用的是stu.name,而在第二個例子中使用的是stu[‘name’]的方式。在《javascript高級程式設計》
引用類型的那一章提到:一般來說,訪問對象屬性時使用的都是點表示法,這也是很多面向對象語言中通用的語法。不過,