mobx-vue 目前已進(jìn)入 mobxjs 官方組織 幾周前我寫了一篇文章描述了 mobx 與 angularjs 結(jié)合使用的方式及目的 (老樹發(fā)新芽—使用 mobx 加速你的 AngularJS 應(yīng)用),,這次介紹一下如何將 MobX 跟 Vue 結(jié)合起來(lái),。 安裝npm i mobx-vue -S 使用mobx-vue 的使用非常簡(jiǎn)單,只需要使用 connect 將你用 mobx 定義的 store 跟 vue component 連接起來(lái)即可: <template> Why MobX/mobx-vue我們知道,,mobx 跟 vue 都是基于 數(shù)據(jù)劫持&依賴收集 的方式來(lái)實(shí)現(xiàn)響應(yīng)式機(jī)制的,。mobx 官方也多次提到
2016年我在構(gòu)建公司級(jí)組件庫(kù)的時(shí)候開始思考一個(gè)問(wèn)題,,我們?nèi)绾卧诖a庫(kù)基于某一框架的情況下,,能以盡可能小的代價(jià)在未來(lái)將組件庫(kù)遷移到其他 框架/庫(kù) 下?總不能基于新的技術(shù)全部重寫一遍吧,,這也太浪費(fèi)生命了,。且不說(shuō)對(duì)于基礎(chǔ)控件而言,交互/行為 邏輯基本上是可確定的,,最多也就是 UI 上的一些調(diào)整,,而且單純?yōu)榱藝L試新技術(shù)耗費(fèi)公司人力物力將基礎(chǔ)庫(kù)推導(dǎo)重寫也是非常不職業(yè)的做法。那么我們只能接受被框架綁架而只能深陷某一技術(shù)棧從此泥潭深陷嗎,?對(duì)于前端這種框架半衰期尤其短的領(lǐng)域而言顯然是不可接受的,,結(jié)果無(wú)非就是要么自己跑路坑后來(lái)人,要么招不到人來(lái)一起填坑… 簡(jiǎn)單來(lái)說(shuō)我們無(wú)法享受新技術(shù)帶來(lái)的種種紅利,。 在 MVVM 架構(gòu)視角下,,越是重型的應(yīng)用其復(fù)雜度越是集中在 M(Model) 跟 VM(ViewModel) 這兩層,尤其是 Model 層,,理論上應(yīng)該是能脫離上層視圖獨(dú)立運(yùn)行獨(dú)立發(fā)布獨(dú)立測(cè)試的存在,。而相應(yīng)的不同視圖框架只是使用了不同綁定語(yǔ)法的動(dòng)態(tài)模板引擎而已,這個(gè)觀點(diǎn)我在前面的幾篇文章里都講述過(guò),。所以只要我們將視圖層做的很薄,,我們遷移的成本自然會(huì)降到一個(gè)可接受的范疇,甚至有可能通過(guò)工具在編譯期自動(dòng)生成不同框架的視圖層代碼,。 要做到 Model 甚至 ViewModel 獨(dú)立可復(fù)用,我們需要的是一種可以幫助我們描述各數(shù)據(jù)模型間依賴關(guān)系圖且框架中立的通用狀態(tài)管理方案,。這期間我嘗試過(guò) ES6 accessor,、redux、rxjs 等方案,,但都不盡如人意,。accessor 過(guò)于底層且異步不友好、redux 開發(fā)體驗(yàn)太差(參考Redux數(shù)據(jù)流管理架構(gòu)有什么致命缺陷,未來(lái)會(huì)如何改進(jìn)?),、rxjs 過(guò)重等等,。直到后來(lái)看到 MobX:MobX 語(yǔ)法足夠簡(jiǎn)單、弱主張(unopinioned),、oop 向,、框架中立等特性正好符合我的需求。 在過(guò)去的一年多里,,我分別在 react,、angularjs、angular 上嘗試過(guò)基于 MobX 構(gòu)建 VM/M 層,,其中有兩個(gè)上線項(xiàng)目,,一個(gè)個(gè)人項(xiàng)目,,實(shí)踐效果基本上也達(dá)到了我的預(yù)期。在架構(gòu)上,,我們只需要使用對(duì)應(yīng)的 connector,,就能基于同一數(shù)據(jù)層,在不同框架下自如的切換,。這樣看來(lái),,這套思路現(xiàn)在就剩 Vue 沒(méi)有被驗(yàn)證了。 在 mobx-vue 之前,,社區(qū)已經(jīng)有一些優(yōu)秀的 connector 實(shí)現(xiàn),,如 movuevue-modex 等,但基本都是基于 vue 的插件機(jī)制且 inspired by vue-rx,,除了使用起來(lái)相對(duì)繁瑣的問(wèn)題外,,最大的問(wèn)題是其實(shí)現(xiàn)基本都是借助 Vue.util.defineReactive 來(lái)做的,也就是說(shuō)還是基于 Vue 自有的響應(yīng)式機(jī)制,,這在一定程度不僅浪費(fèi)了 MobX 的reactive 能力,,而且會(huì)為遷移到其他視圖框架下埋下了不確定的種子(畢竟你無(wú)法確保是 Vue 還是 MobX 在響應(yīng)狀態(tài)變化)。 參考:why mobx-vue(https://github.com/mobxjs/mobx-vue#why-mobx-vue) 理想狀態(tài)下應(yīng)該是由 mobx 管理數(shù)據(jù)的依賴關(guān)系,,vue 針對(duì) mobx 的響應(yīng)做出 re render 動(dòng)作即可,,vue 只是一個(gè)單純的動(dòng)態(tài)模板渲染引擎,就像 react 一樣,。 在這樣的一個(gè)背景下,,mobx-vue 誕生了。 mobx-vue 是如何運(yùn)作的既然我們的目的是將 vue 變成一個(gè)單純的模板渲染引擎(vdom),,并且使用 mobx 響應(yīng)式機(jī)制取代 vue 的響應(yīng)式,,那么只要我們劫持到 Vue 的組件裝載及更新方法,然后在組件裝載的時(shí)候收集依賴,,在依賴發(fā)生變更時(shí)更新組件即可,。 以下內(nèi)容與其叫做 mobx-vue 是如何運(yùn)作的,不如叫 Vue 源碼解析??: 我們知道 Vue 通常是這樣初始化的: new Vue({ el: '#app', render: h => h(App)}); 那么找到 Vue 的構(gòu)造函數(shù),, function Vue (options) { 跟進(jìn)到 if (vm.$options.el) { 跟進(jìn) if (process.env.NODE_ENV !== 'production' && config.performance && mark) { 從這里可以看到,, constructor ( 看到這里,,我們能發(fā)現(xiàn),組件 裝載/更新 的發(fā)起者是: 中心思想就是用 MobX 的響應(yīng)式機(jī)制接管 Vue 的 Watcher,,將 Vue 降級(jí)成一個(gè)純粹的裝載 vdom 的組件渲染引擎。 核心實(shí)現(xiàn)很簡(jiǎn)單: const { $mount } = Component.prototype; 完整代碼在這里:https://github.com/mobxjs/mobx-vue/blob/master/src/connect.ts 最后尤大大之前說(shuō)過(guò):mobx react 是更繁瑣的 Vue,,本質(zhì)上來(lái)看確實(shí)是這樣的,,mobx react 組合提供的能力恰好是 Vue 與生俱來(lái)的。而 mobx-vue 做的事情則剛好相反:將 Vue 降級(jí)成 react 然后再配合 MobX 升級(jí)成 Vue ??,。這確實(shí)很怪異,。但我想說(shuō)的是,我們的初衷并不是說(shuō) Vue 的響應(yīng)式機(jī)制實(shí)現(xiàn)的不好從而要用 MobX 替換掉,,而是希望借助 MobX 這個(gè)相對(duì)中立的狀態(tài)管理平臺(tái),,面向不同視圖層技術(shù)提供一種相對(duì)通用的數(shù)據(jù)層編程范式,從而盡量抹平不同框架間的語(yǔ)法及技術(shù)棧差異,,以便為開發(fā)者提供更多的視圖技術(shù)的決策權(quán)及可能性,,而不至于被某一框架綁架裹挾。 【關(guān)于投稿】 如果大家有原創(chuàng)好文投稿,,請(qǐng)直接給公號(hào)發(fā)送留言,。 ① 留言格式: 覺(jué)得本文對(duì)你有幫助,?請(qǐng)分享給更多人 關(guān)注「前端大全」,,提升前端技能 |
|