<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 為什么要依賴收集? **先舉個栗子??** 我們現在有這么一個 Vue 對象。 ``` new Vue({ template: `<div> <span>{{text1}}</span> <span>{{text2}}</span> <div>`, data: { text1: 'text1', text2: 'text2', text3: 'text3' } }); ``` 然后我們做了這么一個操作。 ``` this.text3 = 'modify text3'; ``` 我們修改了 `data` 中 `text3` 的數據,但是因為視圖中并不需要用到 `text3` ,所以我們并不需要觸發上一章所講的 `cb` 函數來更新視圖,調用 `cb` 顯然是不正確的。 **再來一個栗子??** 假設我們現在有一個全局的對象,我們可能會在多個 Vue 對象中用到它進行展示。 ``` let globalObj = { text1: 'text1' }; let o1 = new Vue({ template: `<div> <span>{{text1}}</span> <div>`, data: globalObj }); let o2 = new Vue({ template: `<div> <span>{{text1}}</span> <div>`, data: globalObj }); ``` 這個時候,我們執行了如下操作。 ``` globalObj.text1 = 'hello,text1'; ``` 我們應該需要通知 `o1` 以及 `o2` 兩個vm實例進行視圖的更新,「依賴收集」會讓 `text1` 這個數據知道“哦~有兩個地方依賴我的數據,我變化的時候需要通知它們~”。 最終會形成數據與視圖的一種對應關系,如下圖。 ![](https://img.kancloud.cn/5f/b8/5fb8adff0d214c2d2364b40b475e62d5_610x270.gif) 接下來我們來介紹一下「依賴收集」是如何實現的。 ## 訂閱者 Dep 首先我們來實現一個訂閱者 Dep ,它的主要作用是用來存放 `Watcher` 觀察者對象。 ``` class Dep { constructor () { /* 用來存放Watcher對象的數組 */ this.subs = []; } /* 在subs中添加一個Watcher對象 */ addSub (sub) { this.subs.push(sub); } /* 通知所有Watcher對象更新視圖 */ notify () { this.subs.forEach((sub) => { sub.update(); }) } } ``` 為了便于理解我們只實現了添加的部分代碼,主要是兩件事情: 1. 用 `addSub` 方法可以在目前的 `Dep` 對象中增加一個 `Watcher` 的訂閱操作; 2. 用 `notify` 方法通知目前 `Dep` 對象的 `subs` 中的所有 `Watcher` 對象觸發更新操作。 ## 觀察者 Watcher ``` class Watcher { constructor () { /* 在new一個Watcher對象時將該對象賦值給Dep.target,在get中會用到 */ Dep.target = this; } /* 更新視圖的方法 */ update () { console.log("視圖更新啦~"); } } Dep.target = null; ``` ## 依賴收集 接下來我們修改一下 `defineReactive` 以及 Vue 的構造函數,來完成依賴收集。 我們在閉包中增加了一個 Dep 類的對象,用來收集 `Watcher` 對象。在對象被「讀」的時候,會觸發 `reactiveGetter` 函數把當前的 `Watcher` 對象(存放在 Dep.target 中)收集到 `Dep` 類中去。之后如果當該對象被「**寫**」的時候,則會觸發 `reactiveSetter` 方法,通知 `Dep` 類調用 `notify` 來觸發所有 `Watcher` 對象的 `update` 方法更新對應視圖。 ``` function defineReactive (obj, key, val) { /* 一個Dep類對象 */ const dep = new Dep(); Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { /* 將Dep.target(即當前的Watcher對象存入dep的subs中) */ dep.addSub(Dep.target); return val; }, set: function reactiveSetter (newVal) { if (newVal === val) return; /* 在set的時候觸發dep的notify來通知所有的Watcher對象更新視圖 */ dep.notify(); } }); } class Vue { constructor(options) { this._data = options.data; observer(this._data); /* 新建一個Watcher觀察者對象,這時候Dep.target會指向這個Watcher對象 */ new Watcher(); /* 在這里模擬render的過程,為了觸發test屬性的get函數 */ console.log('render~', this._data.test); } } ``` ## 小結 總結一下。 首先在 `observer` 的過程中會注冊 `get` 方法,該方法用來進行「**依賴收集**」。在它的閉包中會有一個 `Dep` 對象,這個對象用來存放 Watcher 對象的實例。其實「**依賴收集**」的過程就是把 `Watcher` 實例存放到對應的 `Dep` 對象中去。`get` 方法可以讓當前的 `Watcher` 對象(Dep.target)存放到它的 subs 中(`addSub`)方法,在數據變化時,`set` 會調用 `Dep` 對象的 `notify` 方法通知它內部所有的 `Watcher` 對象進行視圖更新。 這是 `Object.defineProperty` 的 `set/get` 方法處理的事情,那么「**依賴收集**」的前提條件還有兩個: 1. 觸發 `get` 方法; 2. 新建一個 Watcher 對象。 這個我們在 Vue 的構造類中處理。新建一個 `Watcher` 對象只需要 new 出來,這時候 `Dep.target` 已經指向了這個 new 出來的 `Watcher` 對象來。而觸發 `get` 方法也很簡單,實際上只要把 render function 進行渲染,那么其中的依賴的對象都會被「讀取」,這里我們通過打印來模擬這個過程,讀取 test 來觸發 `get` 進行「依賴收集」。 本章我們介紹了「依賴收集」的過程,配合之前的響應式原理,已經把整個「響應式系統」介紹完畢了。其主要就是 `get` 進行「依賴收集」。`set` 通過觀察者來更新視圖,配合下圖仔細捋一捋,相信一定能搞懂它! ![](https://img.kancloud.cn/3f/32/3f32fe9400f1f726e6d10eadd342b277_1460x728.gif) 注:本節代碼參考[《響應式系統的依賴收集追蹤原理》](https://github.com/answershuto/VueDemo/blob/master/%E3%80%8A%E5%93%8D%E5%BA%94%E5%BC%8F%E7%B3%BB%E7%BB%9F%E7%9A%84%E4%BE%9D%E8%B5%96%E6%94%B6%E9%9B%86%E8%BF%BD%E8%B8%AA%E5%8E%9F%E7%90%86%E3%80%8B.js)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看