摘要:在原理中,最重要的部分就是如何實現數據的觀測,依賴的收集,視圖的更新。本文講的就是這三個的簡單實現。這樣做代碼似乎有點丑,我們在設置屬性觸發會發生函數,有沒有一種更加智能的方式來實現通知變化呢。
在vue原理中,最重要的部分就是如何實現數據的觀測,依賴的收集,視圖的更新。本文講的就是Observer, Dep, Watcher這三個的簡單實現。
pub(publish)表示發布者,sub(subscribe)表示訂閱者, cb(callback)表示回調函數
如果你覺得這篇講的對你有所幫助,請幫我點個star
Observer的作用簡單來說就是讓object對象的屬性都用Object.defineProperty()來進行定義,這樣當獲取object的屬性,或者修改屬性的時候,就能夠觸發get,set達到數據的觀測的效果。
class Observer { constructor(value) { this.value = value this.walk(this.value) } walk (value) { // 遞歸遍歷value的屬性 Object.keys(value).forEach((key) = > { defineReactive(value, key, value[key]) }) } } function defineReactive(obj, key ,val) { let childOb = observe(val) Obeject.defineProperty(obj, key, { enumerable: true, configurable: true, get() { console.log("") return val }, set(newVal) { console.log("") val = newVal childOb = observe(val) } }) } function observe (value) { if (typeof value === "object" && !Array.isArray(value)) { value = new Observer(value) } }
defineReactive的作用就是給對象的屬性進行簡單的數據觀測,一旦值獲取或者設置就會觸發一些行為.因為一個對象的屬性可能還是對象,所以在這里我們添加observe函數來遍歷值,讓一個對象的屬性的屬性還是可以進行觀測的,簡單呢來說的意思就是讓所有屬性都可以進行忽略。當然在實際情況中,我們還需要考慮數組的情況,但都大同小異。
這樣做代碼似乎有點丑,我們在設置屬性觸發set會發生console.log()函數,有沒有一種更加智能的方式來實現通知變化呢。這里我們就需要用消息訂閱器來進行實現,這樣做我們就不需要通過觀察console.log()輸出的值來看進行的情況,我們只需要在set方法里邊加一個通知,一旦值發生變化,就通知外邊值發生了改變
Dep的作用就是用來收集屬性值的變化,一旦set方法觸發的時候,就更新視圖。那就準備一個數組來進行收集吧!
下面是Dep的實現:
class Dep { constructor() { this.subs = [] } addSub (sub) { this.subs.push(sub) } notify () { const subs = this.subs.slice() subs.forEach((sub) => { sub.update() // 視圖更新 }) } }
上面就是Dep的簡單實現,addSub的作用是增加訂閱者,因為有很多訂閱者,我們需要用一個數組將它進行存儲,notify()函數的作用就是當set發生的時候,進行通知,update()這個函數待會在watcher中會講到。實現了Dep我們是不是該更改了set()函數了呢,下面是defineReactive()修改后的代碼
function defineReactive(obj, key ,val) { let dep = new Dep() // 畢竟要使用Dep的方法 let childOb = observe(val) Obeject.defineProperty(obj, key, { enumerable: true, configurable: true, get() { return val }, set(newVal) { val = newVal childOb = observe(val) dep.notify() // 因為數據改變了,我們就通知Dep } }) }
一旦觸發set,就調用dep.notify(),notify的作用就是針對訂閱者遍歷進行更新。
Watcher的簡單實現:watcher的作用,就是當狀態發生改變的時候,更新視圖,我們可以假設
class Watcher { constructor (vm, cb, expOrFn) { this.vm = vm // 這表示一個Vue的實例 this.cb = cb // 這里需要考慮expOrFn是字符串或者函數的情況 // 這里做一個簡化,只考慮函數的情況 this.getter = expOrFn this.value = this.get() } get () { Dep.target = this const vm = this.vm value = this.getter.call(this.vm, vm) Dep.target = null return value } update () { this.run() } run () { const value = this.get() if (value !== this.value) { const oldValue = this.value this.value = value this.cb.call(this.vm, value, oldValue) } } }
Watcher的簡單實現就完成了,在Dep()構造函數中,我們使用了sub.update()這行代碼,而update函數是Watcher里邊的方法,說明每一個sub都是Wathcer的實例,問題是我們應該如何通過addSub()這個方法,將Watcher加入到subs這個數組中盡心存儲呢,答案還是在defineReactive()里邊進行修改
function defineReactive(obj, key ,val) { let dep = new Dep() // 畢竟要使用Dep的方法 let childOb = observe(val) Obeject.defineProperty(obj, key, { enumerable: true, configurable: true, get() { if(Dep.target) { dep.addSub(Dep.target) } return val }, set(newVal) { val = newVal childOb = observe(val) dep.notify() // 因為數據改變了,我們就通知Dep } }) }
這樣是不是就實現了往Dep里邊加Watcher了,vue源碼中比這個復雜的多,各種參數,看著頭大。本文的宗旨就是通過簡化讓你了解內部原理,如果需要更深入了解就需要閱讀源碼了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/51579.html
摘要:后端路由簡介路由這個概念最先是后端出現的。前端路由模式隨著的流行,異步數據請求交互運行在不刷新瀏覽器的情況下進行。通過這些就能用另一種方式來實現前端路由了,但原理都是跟實現相同的。 后端路由簡介 路由這個概念最先是后端出現的。在以前用模板引擎開發頁面時,經常會看到這樣 http://www.xxx.com/login 大致流程可以看成這樣: 瀏覽器發出請求 服務器監聽到80端口(或4...
答案自己谷歌或百度找。 一、來源背景 面試題是來自微博@牛客網發布的真實大廠前端面經題目,我一直在收集題目長期一個一個的記錄下來的,可能會有重復,但基本前端的面試大綱和需要掌握的知識都在其中了,面試題僅做學習參考,學習者閱后也要用心鉆研其中的原理,重要知識需要系統學習、透徹學習,形成自己的知識鏈。 二、532道前端真實大廠面試題 express和koa的對比,兩者中間件的原理,koa捕獲異常多種情...
答案自己谷歌或百度找。 一、來源背景 面試題是來自微博@牛客網發布的真實大廠前端面經題目,我一直在收集題目長期一個一個的記錄下來的,可能會有重復,但基本前端的面試大綱和需要掌握的知識都在其中了,面試題僅做學習參考,學習者閱后也要用心鉆研其中的原理,重要知識需要系統學習、透徹學習,形成自己的知識鏈。 二、532道前端真實大廠面試題 express和koa的對比,兩者中間件的原理,koa捕獲異常多種情...
答案自己谷歌或百度找。 一、來源背景 面試題是來自微博@牛客網發布的真實大廠前端面經題目,我一直在收集題目長期一個一個的記錄下來的,可能會有重復,但基本前端的面試大綱和需要掌握的知識都在其中了,面試題僅做學習參考,學習者閱后也要用心鉆研其中的原理,重要知識需要系統學習、透徹學習,形成自己的知識鏈。 二、532道前端真實大廠面試題 express和koa的對比,兩者中間件的原理,koa捕獲異常多種情...
摘要:雙向數據綁定指的是,將對象屬性變化與視圖的變化相互綁定。數據雙向綁定已經了解到是通過數據劫持的方式來做數據綁定的,其中最核心的方法便是通過來實現對屬性的劫持,達到監聽數據變動的目的。和允許觀察數據的更改并觸發更新。 1 MVVM 雙向數據綁定指的是,將對象屬性變化與視圖的變化相互綁定。換句話說,如果有一個擁有name屬性的user對象,與元素的內容綁定,當給user.name賦予一個新...
閱讀 2368·2021-11-18 10:07
閱讀 2318·2021-09-22 15:59
閱讀 3077·2021-08-23 09:42
閱讀 2276·2019-08-30 15:44
閱讀 1191·2019-08-29 15:06
閱讀 2303·2019-08-29 13:27
閱讀 1210·2019-08-29 13:21
閱讀 1412·2019-08-29 13:13