Vue數據雙向綁定(面試必備) 極簡版


  我又來吹牛逼了,這次我們簡單說一下vue的數據雙向綁定,我們這次不背題,而是要你理解這個流程,保證讀完就懂,逢人能講,面試必過,如果沒做到,請再來看一遍,走起:

  

  介紹雙向數據之前,我們先解釋幾個名詞:

 

  1、什么是setter、getter ?

  答:首先,別誤以為他們就是一會要說的get、set,我們先看一句定義:

    對象有兩種屬性:(1)數據屬性,就是我們經常使用的屬性(2)訪問器屬性,也稱存取器屬性(存取器屬性就是一組獲取和設置值的函數

   

  再看一行代碼:

  

  log打印出來的如下:

  

  數據屬性就是a和b;

  get和set就是關鍵字 它們后面各自對應一個函數,這個函數就是上面紅字部分所講的,存儲器屬性。

  get對應的方法稱為getter,負責獲取值,它不帶任何參數。set對應的方法為setter,負責設置值,在它的函數體中,一切的return都是無效的。

 

  2、什么是Object.defineProperty() ?

  答:老規矩走起,我們先看一句定義:

  對象是由多個名/值對組成的無序的集合。對象中每個屬性對應任意類型的值。

  

  定義對象可以使用構造函數或字面量的形式:

  

  

  除了以上添加屬性的方式,當然還可以使用Object.defineProperty定義新屬性或修改原有的屬性;

  語法:

  Object.defineProperty(obj, prop, descriptor)

  參數:

  obj:必需。目標對象;
  prop:必需。需定義或修改的屬性的名字;
  descriptor:必需。目標屬性所擁有的特性;

  返回值:

  傳入函數的對象,即第一個參數obj;

 

  OK,定義介紹完了,我們現在說一下一會關於雙向綁定我們要用到的知識點:存取器描述;(誒?你是不是發現和上面好像有點關系)

  

  對頭,它是這樣使用的:

  

 

  現在無論是你獲取還是設置我們都可以接到通知,是不是有一點雙向數據綁定的影子了,別急下面還有;

  

  OK,我終於叨叨完沒用的了,現在開始說正題,如何理解Vue的雙向數據綁定,哈哈,先來一個定義:

  Vue是采用數據劫持結合發布/訂閱模式的方式,通過Object.defineProperty()來劫持各個屬性的settergetter,在數據變動時發布消息給訂閱者,觸發相應的監聽回調。

 

  我們來看一個很粗暴的栗子,low版雙向綁定:

  

 

  是不是有點明白了呢,當然這也不是全部,我們剛剛說的大概就是下面Observer的部分,對每個vue中的data中定義的屬性循環用Object.defineProperty()實現數據劫持,以便利用其中的setter和getter,然后通知訂閱者,訂閱者會觸發它的update方法,對視圖進行更新。

 

  

 

  別急,下面也很簡單:

  Dep,它就像一個依賴管理一樣,小伙伴又問啥是依賴管理倪? 上圖!

  

  我用一個例子來解釋一下上面這張圖 下面高能預警:

  在vue中v-model,v-name,{{}}等都可以對數據進行展示,也就是說假如一個屬性都通過這三個指令了,那么每當這個屬性改變的時候,相應的這個三個指令的html視圖也必須改變;

  於是vue中就是每當有這樣的可能用到雙向綁定的指令,就在一個Dep中增加一個訂閱者(addSub),其訂閱者只是更新自己的指令對應的數據,也就是v-model='name'和{{name}}有兩個對應的訂閱者,各自管理自己的地方;

  每當屬性的set方法觸發,就循環更新Dep中的訂閱者(notify);

 

  OK,Dep是不是很明白了呢

  集合上面的那張圖來看,就是Observer一旦有了set觸發,就會通知到Dep,那Dep接到通知之后呢?從圖上來看,下面所講的就應該是Compile了,也很簡單:

  首先,先要知道它負責干什么?

  compile主要做的事情是解析模板指令,將模板中的變量替換成數據

  其次知道它什么時候要工作,只有兩種情況,先上圖:

  

  

  1)初始化,init的時候 初始化渲染頁面視圖;

  2)將每個指令對應的節點綁定更新函數,添加監聽數據的訂閱者

 

  Dep負責維護依賴,而訂閱者則來自於compile,一旦有數據變動,則會綁定更新函數,此時也就是產生了訂閱者,這個時候Dep內就增加了一個訂閱者,而一旦數據變動,則會收到通知,更新視圖;

 

  好了,你是不是覺得上面這行說不通,或是讀不通,當然,因為上面的這個流程了缺少了,我們最后要說的Watcher我把上面這句話補全,就是Watcher的工作了;

 

  Dep負責維護依賴,而訂閱者則來自於compile,一旦有數據變動,則會通過Watcher綁定更新函數,此時Watcher也向Dep中添加了訂閱者,一旦Dep接到Observer的通知,它就會再去通知WatcherWatcher則會調用自身的update()方法,並觸發Compile中綁定的回調,更新視圖;

 

  

  最后敲黑板:

  首先我們為每個vue屬性用Object.defineProperty()實現數據劫持,為每個屬性分配一個訂閱者集合的管理數組dep;

  然后在編譯的時候在該屬性的數組dep中添加訂閱者,v-model會添加一個訂閱者,{{}}也會,v-bind也會,只要用到該屬性的指令理論上都會;

  接着為input會添加監聽事件,修改值就等於為該屬性賦值,則會觸發該屬性的set方法,在set方法內通知訂閱者數組dep,訂閱者數組循環調用各訂閱者的update方法更新視圖。

 

  參考干貨:

  https://www.cnblogs.com/zhenfei-jiang/p/7542900.html

  https://segmentfault.com/a/1190000006599500

 

  感謝巨人的肩膀

 

  

  

  

  

 

 

 

 

 

 

  

 

 

     

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM