provide / inject
在上一步我們實現了,父子元件,和 props
一樣 provide / inject
也是基於父子元件實現的,相比於 props
它的實現還要更簡單一點。我們先來看看官網上對 provide / inject
的描述。
這對選項需要一起使用,以允許一個祖先元件向其所有子孫後代注入一個依賴,不論元件層次有多深,並在起上下游關係成立的時間裡始終生效。
首先,由官網的例子可知,provide
的值是靜態的,並不會去繫結到 data
中的內容。
so 靜態的,簡單~,那實現一下。
export class Vue extends Event {
···
_init(options) {
···
// 用例項下的 _provide 屬性,儲存傳入的 provide
vm._provide = vm.$options.provide
// 從父元件的 _provide 取對應屬性,若沒有繼續往上找,直到找到根節點
// 若找到根節點還沒有,就使用預設值
let inject = vm._inject = {}
for (let key in vm.$options.inject) {
inject[key] = getProvideForInject(vm, key, vm.$options.inject[key].default)
}
// 代理到 this 下
for (let key in inject) {
proxy(vm, '_inject', key)
}
}
}
複製程式碼
測試程式碼:
import {Vue} from './Vue.mjs'
let test = new Vue({
provide: {
foo: 'bar'
},
components: {
sub: {
inject: {
foo: {default: 'foo'},
bar: {default: 'subBar'}
},
components: {
subSub: {
inject: {
foo: {default: 'foo'},
bar: {default: 'subSubBar'}
}
}
}
}
}
})
let testSubClass = Vue.extend(test.$options.components.sub)
let testSub = new testSubClass({parent: test})
let testSubSubClass = Vue.extend(testSub.$options.components.subSub)
let testSubSub = new testSubSubClass({parent: testSub})
console.log(testSub.foo)
// bar
console.log(testSub.bar)
// subBar
console.log(testSubSub.foo)
// bar
console.log(testSubSub.bar)
// subSubBar
複製程式碼
ok 其實這對屬性的實現挺簡單的,就是取值而已。
到此為止,Vue
中關於資料繫結的部分基本上實現的差不多了(不包括 directives/filters/slot/ref
···這些與頁面渲染的東西)
但也有以下東西沒實現內容簡單就不過多的介紹了
- mixins: 就是
options
的合併 - 生命週期函式: 在特定的時間觸發特定名稱的事件即可
- $nextTick: 可以去看看
JS Event Loop
的相關內容,優先使用微任務來實現
接下來我們來想想,目前我們實現的東西都能幹嘛?
總結
總的來說,我們實現了一個可響應的物件,我們可以拿到這個物件下資料的變化。
通過裝作這些變化,我們實現了 Computed
、Watcher
從而到達了資料變化觸發函式的過程。
於此同時,我們還實現了 Event
來擴充套件這個可響應的結構,讓這個物件擁有了觸發和響應事件的能力。
最後我們實現了例項的樹結構,在這個基礎上實現了 props
和 provide/inject
。
那麼還是那個問題,這個東西能幹嘛用?
我想了想,前端的應用很明顯,我們只要加一個檢視層的渲染函式,就能補充成一個 MVVM
框架,Vue
也是在這個基礎上實現的。當然你也可以實現自己虛擬節點,創造一個屬於你自己的 MVVM
框架。
或者小型的專案,並不需要虛擬節點,那麼繫結一個 HTML
渲染函式即可,所以我們實現的這個可響應結構對於 MVVM
來說,僅僅少了一層 VIEW
,所以我想叫 MVM
也是沒問題的。
但是我想這個東西是純 Js
的,所以能發揮的能力也肯定不僅僅是在前端,我之所以將這個完全的脫離模板來分析,也是想把這塊單獨出來成為一個工具。
對於這個可響應結構,我想了想用處:
- 專案自動化配置,打包,初始化
- 根據配置篩選資料
- ···
對於第一點,假設我們有一個專案的配置(一個 js
物件),然後我們把這個物件變成響應結構,那麼當這個物件發生變化的時候,比如說版本號變動,那麼可以觸發更新程式碼,打包編譯程式碼,傳送程式碼到服務等一些列的步驟。
對於第二點,假設在後端,我們有一堆資料,我們的需求是根據需求去篩選資料,比如 pageNo/pageSize
等等,那麼我們可以根據需求定下一個 js
配置物件,然後針對每個屬性新增一系列定義好的 Watcher
,那麼我們就可以根據這個物件的變動執行特定的方法,而我們所需要做的僅僅是把配置物件的屬性改一下就好,比如說當執行 obj.pageNo = 2
,然後程式就自動的把對應的資料給篩選出來了。
當然,這個可響應的結構的用處遠不至於此,只要以資料驅動或是配置化的地方,都有用武之地。
ok finally 這個系列的文章算是結束了,至於 VUE
中關於,模板解析和虛擬 DOM
的實現,會有單獨的系列,但模板解析大部分是在正則解析,所以可能會沒有。
最後,根據我們的實現,這是最終的產出,一個 MVM 框架,瞭解一下?