vue是一個很是優秀的框架,其優秀的雙向綁定原理,mvvm模型,組件,路由解析器等,很是的靈活方便,也使開發者可以着重於數據處理,讓開發者更清晰的設計本身的業務。html
雙向綁定,就是數據變化的時候,自動觸發視圖的變化。vue
咱們都理解,vue2.0中,雙向綁定的核心爲Object.defineProperty(obj, prop, descriptor)
,方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象git
參數obj
爲要在其上定義屬性的對象。
參數prop
爲要定義或修改的屬性的名稱。
參數descriptor
爲將被定義或修改的屬性描述符。
github
返回被傳遞給函數的對象。
瀏覽器
咱們能夠新建一個項目,用來模擬及學習vue
雙向綁定的相關內容框架
+ vue相關 + |- 雙向綁定原理 + |- js + |- myVue.js + |- index.html
修改index.html中的內容,引入本身建立的myVue.js。mvvm
+ <!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> + + <script src="./js/myVue.js"></script> + </body> + </html>
編輯myVue.js
的內容,來嘗試一下Object.defineProperty(obj, prop, descriptor)
這個APIide
+ var data = { + a: 1 + } + Object.defineProperty(data, 'a', {// 爲data中的a進行攔截,讀取a的時候返回本身新建的_a的值,設置a的值的時候,設置到_a上。這樣,開發者對a的操做,都會映射到咱們新建的虛擬的_a變量上 + configurable: true, // 是否容許刪除屬性,默認true + enumerable: true, // 是否容許遍歷,默認true + get: function () { + console.log('我被讀取了,返回了_a的值', this._a) + return this._a + }, + set(value) { + // this.a = value; + this._a = value; + console.log('我被設置了,被設置的值爲', this._a, '並放進了a的對象中') + } + })
在瀏覽器中,打開頁面,並查看控制檯,對data.a
進行操做函數
data.a myVue.js:8 我被讀取了,返回了_a的值 undefined undefined —————————————————————————————————————————————————————————————————————————————— data.a = 10 myVue.js:14 我被設置了,被設置的值爲 10 並放進了a的對象中 10 —————————————————————————————————————————————————————————————————————————————— data.a myVue.js:8 我被讀取了,返回了_a的值 10 10
能夠看到,咱們對data.a進行的操做,實際改變的變量是咱們已經攔截的_a
變量。
目前出現的問題是,第一次讀取的時候,這個值沒有被設置上,在下面來模擬解決方案post
聲明概念_
開頭的變量一版爲私有變量,外部沒法訪問,可是咱們如今在控制檯中輸入並修改私有變量data._a
data._a 10 —————————————————————————————————————————————————————————————————————————————— data._a = 20 20 —————————————————————————————————————————————————————————————————————————————— data._a 20 —————————————————————————————————————————————————————————————————————————————— data.a myVue.js:8 我被讀取了,返回了_a的值 20 20
卻能夠拿到私有變量中的_a
的值,也能夠進行無攔截的修改,這顯然是咱們所不但願的
因此咱們能夠爲Object.defineProperty(obj, prop, descriptor)
來進行封裝一次,把咱們理解的_a
變成一個私有變量
修改myVue.js
的內容爲以下內容,
var data = { a: 1 } myDefineProperty(data, 'a') function myDefineProperty(obj,key){//對Object.defineProperty進行一次攔截,使外界沒法訪問私有變量value var value = obj[key]; Object.defineProperty(obj,key,{// 爲data增長 configurable: true, // 是否容許刪除屬性,默認true enumerable: true, // 是否容許遍歷,默認true get: function () { console.log('我被讀取了,返回了value的值', value) return value }, set(newValue) { value = newValue; console.log('我被設置了,被設置的值爲', newValue, '並放進了value的對象中') } }) }
而後再查看控制檯
data._a undefined —————————————————————————————————————————————————————————————————————————————— data.value undefined —————————————————————————————————————————————————————————————————————————————— data.a myVue.js:12 我被讀取了,返回了value的值 1 1 ——————————————————————————————————————————————————————————————————————————————
開發者就沒法自行操做咱們設計的私有變量value的內容了
自此,咱們解決了,對一個對象屬性的攔截,而且阻止了用戶對咱們設計的私有變量進行操做
咱們知道了攔截屬性以後,那麼就進一步來實現,一個簡單的雙向綁定
咱們修改一下index.html
中的內容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> + <input type="text" @change='changeIpt'> + <p id='changeValue'></p> </head> <body> <script src="./js/myVue.js"></script> </body> </html>
並在myVue.js
中,在set中添加雙向綁定的操做
var data = { a: 1 } myDefineProperty(data, 'a') + var ipt = document.getElementById('ipt'); + ipt.oninput = function(e){ + data.a = e.target.value + } function myDefineProperty(obj,key){ var value = obj[key]; Object.defineProperty(obj,key,{// 爲data增長 configurable: true, // 是否容許刪除屬性,默認true enumerable: true, // 是否容許遍歷,默認true get: function () { console.log('我被讀取了,返回了value的值', value) return value }, set(newValue) { value = newValue; + document.getElementById('iptValue').innerText = newValue; + ipt.value = newValue; console.log('我被設置了,被設置的值爲', newValue, '並放進了value的對象中') } }) }
而後咱們在input
框裏輸入內容,便表現出了雙向綁定的能力。
記得打開控制檯哦!~下方爲錄製的屏幕,可能沒法正常顯示,能夠點擊上方demo來查看
以爲好的話,能夠給個人 github點個star
哦