<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [項目地址](https://github.com/fujiazhang/vue) [TOC] 在開始之前需要有一些基本的認識 # 數據驅動 Vue.js 一個核心思想是數據驅動。所謂數據驅動,是指視圖是由數據驅動生成的,我們對視圖的修改,不會直接操作 DOM,而是通過修改數據。它相比我們傳統的前端開發,如使用 jQuery 等前端庫直接修改 DOM,大大簡化了代碼量。特別是當交互復雜的時候,只關心數據的修改會讓代碼的邏輯變的非常清晰,因為 DOM 變成了數據的映射,我們所有的邏輯都是對數據的修改,而不用碰觸 DOM,這樣的代碼非常利于維護。 在 Vue.js 中我們可以采用簡潔的模板語法來聲明式的將數據渲染為 DOM: ~~~ <div id="app"> {{ message }} </div> ~~~ ~~~ var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } }) ~~~ 最終它會在頁面上渲染出`Hello Vue`。 # vue2響應式核心原理 直接上代碼了,vue2 defineProperty api的實現基于如下代碼: ![](https://img.kancloud.cn/f5/c1/f5c162fa9a0f785f906942012f893950_1322x1130.png) # vue3響應式核心原理 直接上代碼了,proxy: ![](https://img.kancloud.cn/31/31/3131c693d31e1aec433ffc75afd15810_1462x1152.png) 可以看到我們proxy的實現要簡潔一些,另外性能有瀏覽器優化,性能要比defineProperty好。 # 發布訂閱模式 ## 發布訂閱和觀察者模式 這兩種模式在vue中有各自的運用場景,兩種模式本質是相同的,但是是有區別的,他們經常被混為一談。 在vue中的自定義事件 就是一個典型的發布訂閱模式,比如下面截圖的代碼, ![](https://img.kancloud.cn/fe/c3/fec3fe74148a949d5c00b615e6a6698a_792x420.png) 又比如我們兄弟組件傳值可以用eventBus: ![](https://img.kancloud.cn/c4/1e/c41eb77e8eb93497c5989dcafdccad78_1420x798.png) ### 發布者訂閱者模式 ![](https://img.kancloud.cn/cb/ee/cbeec9f3f0846f23d96d87495a0ba7e8_1512x1104.png) ### 觀察者模式 ![](https://img.kancloud.cn/be/93/be937280d434f6f26fbc2d17a1f86187_1286x1048.png) ## 關于兩種模式的總結 **觀察者模式**:觀察者模式是有具體目標調度,比如事件觸發,Dep就會去調用觀察者的方法,所以觀察者和發布者之間存在依賴(強耦合) **發布訂閱模式**:發布訂閱模式由調度中心調用,因此發布者和訂閱者不需要知道對方存在。 ![](https://img.kancloud.cn/7e/ef/7eef45585bc20349cae4172bb2f207ae_1002x706.png) (圖片源自互聯網) # 正餐開始 乞丐最小版本vue整體分析如下 ![](https://img.kancloud.cn/87/33/8733cea9fa519eadd9de5cb0808dad43_756x460.png) vue: 將data中的成員注入到vue實例,并把data中的成員專程getter/setter observer: 能夠將數據對象所有屬性監聽,變化通知Dep。 ## Vue模塊 * 負責接收初始化參數 * 負責把data中的屬性轉換成getter/setter * 負責調用observer監聽data中所有屬性的變化 * 負責調用compiler解析指令/差值表達式 代碼實現: ![](https://img.kancloud.cn/20/d5/20d59091baa63921a8f597889992296a_1532x1180.png) ## Observer模塊 * 負責把data選項中的屬性轉換成響應式數據 * data中的某個屬性也是對象,把該屬性轉換成響應式數據 * 數據變化發送通知 ![](https://img.kancloud.cn/f3/c3/f3c394cf2aa1218ffc5dded7f9308909_1280x1090.png) ![](https://img.kancloud.cn/cf/76/cf766a9b25e0ae10141270147a014f0f_1278x980.png) ## Compiler * 負責編譯模版,解析指令/差值表達式 * 負責頁面的首次渲染 * 當數據變化后 重新渲染視圖 代碼如下: ``` /** * @description: * 1.負責編譯模版,解析指令/差值表達式 * 2.負責頁面的首次渲染 * 3.當數據變化后重新渲染視圖 * 未引入虛擬dom直接操作的實dom */ class Compiler { constructor(vm) { this.el = vm.$el this.vm = vm this.compile(this.el) } /** * @description: 編譯模版,處理文本和元素節點 */ compile(el) { let childNodes = el.childNodes Array.from(childNodes).forEach(node = >{ if (this.isTextNode(node)) { this.compileText(node) } else if (this.isElement(node)) { this.compileElement(node) } //判斷下是否還有字節點 if (node.childNodes && node.childNodes.length) { this.compile(node) } }) } /** * @description: 變異元素節點 處理指令 */ compileElement(node) { // console.log(node.attributes) Array.from(node.attributes).forEach(attr = >{ let attrName = attr.name if (this.isDirective(attrName)) { attrName = attrName.substr(2) let key = attr.value this.update(node, key, attrName) } }) } update(node, key, attrName) { let updateFn = this[(attrName + 'Update')] updateFn && updateFn.call(this, node, this.vm[key], key) } /** * @description: 處理v-text */ textUpdate(node, value, key) { node.textContent = value //創建watcher對象 數據改變更新試圖 new Watcher(this.vm, key, (newValue) = >{ node.textContent = newValue }) } /** * @description: 處理v-model */ modelUpdate(node, value, key) { node.value = value //創建watcher對象 數據改變更新試圖 new Watcher(this.vm, key, (newValue) = >{ node.value = newValue }) // 雙向綁定 node.addEventListener('input', () = >{ this.vm[key] = node.value }) } /** * @description: 編譯文本節點,處理差值表達式 */ compileText(node) { let reg = /\{\{(.+?)\}\}/let value = node.textContent if (reg.test(value)) { let key = RegExp.$1.trim() node.textContent = value.replace(reg, this.vm[key]) //創建watcher對象 數據改變更新試圖 new Watcher(this.vm, key, (newValue) = >{ node.textContent = newValue }) } } /** * @description: 判斷元素屬性是否指令 */ isDirective(attrName) { return attrName.startsWith('v-') } /** * @description: 判斷節點是否是文本節點 */ isTextNode(node) { return node.nodeType === 3 //node接點屬性3為本文 1為元素 } /** * @description: 判斷節點是否是元素節點 */ isElement(node) { return node.nodeType === 1 //node接點屬性3為本文 1為元素 } } ``` ## Dep * 收集依賴、添加觀察者(watcher * 通知所有的觀察者 ![](https://img.kancloud.cn/db/ca/dbca6b1d95b97d4abef6054d7cd7a432_982x316.png) 代碼如下: ![](https://img.kancloud.cn/79/e7/79e7d47926cbfec15c5963dc221f69f3_1096x920.png) ## watcher * 當數據變化出發依賴,dep通知所有的watcher實例更新視圖 * 自身實例化的時候往dep中添加自己 ![](https://img.kancloud.cn/1a/ad/1aadc46c9140ba79c17e240ed23d71b1_1040x326.png) ![](https://img.kancloud.cn/2f/ca/2fca88eb1adad4af83b394a8ba639ee7_996x1054.png) ## 雙向綁定 * 數據變化 改變視圖 * 視圖變化 改變數據 ![](https://img.kancloud.cn/78/f9/78f94cdf62c003a88ac96810c519935c_1212x634.png)
                  <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>

                              哎呀哎呀视频在线观看