久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

基于 MobX 構(gòu)建視圖框架無(wú)關(guān)的數(shù)據(jù)層-與 Vue 的結(jié)合

 就這樣了__ 2018-07-06


來(lái)源:kuitos

github.com/kuitos/kuitos.github.io/issues/39


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>
   
<section>
       
<p v-text='amount'></p>
       
<p v-for='user in users' :key='user.name'>{{user.name}}</p>
   
</section>
</template>
<script lang='ts'>
   
import { Connect } from 'mobx-vue';
   
import Vue from 'vue';
   
import Component from 'vue-class-component';
   
class ViewModel {
       
@observable users = [];
       
@computed get amount() { return this.users.length }
       
@action fetchUsers() {}
   
}
   
@Connect(new ViewModel())
   
@Component()
   
export default class App extends Vue {
       mounted
() {
           
this.fetchUsers();
       
}
   
}
</script>

Why MobX/mobx-vue

我們知道,,mobx 跟 vue 都是基于 數(shù)據(jù)劫持&依賴收集 的方式來(lái)實(shí)現(xiàn)響應(yīng)式機(jī)制的,。mobx 官方也多次提到 inspired by vue,那么我們?yōu)槭裁催€要將兩個(gè)幾乎一樣的東西結(jié)合起來(lái)呢,?

Yes, it’s weird.

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) {
 
......
 
this._init(options)
}

跟進(jìn)到_init方法,,除了一系列組件初始化行為外,最關(guān)鍵是最后一部分的 $mount 邏輯:

if (vm.$options.el) {
 vm
.$mount(vm.$options.el)
}

跟進(jìn) $mount 方法,,以 web runtime 為例:

if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
   updateComponent
= () => {
       
...
   
}
} else {
   updateComponent
= () => {
       vm
._update(vm._render(), hydrating)
   
}
}
vm
._watcher = new Watcher(vm, updateComponent, noop)

從這里可以看到,,updateComponent 方法將是組件更新的關(guān)鍵入口,跟進(jìn) Watcher 構(gòu)造函數(shù),,看 Vue 怎么調(diào)用到這個(gè)方法的:

constructor (
   vm
: Component,
   expOrFn
: string | Function,
   cb
: Function,
   options
?: Object
 
) {
   
...
   
this.expression = process.env.NODE_ENV !== 'production'
     
? expOrFn.toString()
     
: ''
   
// parse expression for getter
   
if (typeof expOrFn === 'function') {
     
this.getter = expOrFn
   
} else {
     
this.getter = parsePath(expOrFn)
     
...
   
}
   
this.value = this.lazy
     
? undefined
     
: this.get()
get () {
   
...
   
try {
     value
= this.getter.call(vm, vm)
   
} catch (e) {
     
...
 
}

看到這里,,我們能發(fā)現(xiàn),組件 裝載/更新 的發(fā)起者是: value = this.getter.call(vm, vm) ,而我們只要通過(guò) vm._watcher.getter 的方式就能獲取相應(yīng)的方法引用,, 即 updateComponent := vm._watcher.getter,。所以我們只要在 $mount 前將 MobX 管理下的數(shù)據(jù)植入組件上下文供組件直接使用,在$mount 時(shí)讓 MobX 收集相應(yīng)的依賴,,在 MobX 檢測(cè)到依賴更新時(shí)調(diào)用 updateComponent 即可,。這樣的話既能讓 MobX 的響應(yīng)式機(jī)制通過(guò)一種簡(jiǎn)單的方式 hack 進(jìn) Vue 體系,同時(shí)也能保證組件的原生行為不受到影響(生命周期鉤子等),。

中心思想就是用 MobX 的響應(yīng)式機(jī)制接管 Vue 的 Watcher,,將 Vue 降級(jí)成一個(gè)純粹的裝載 vdom 的組件渲染引擎。

核心實(shí)現(xiàn)很簡(jiǎn)單:

const { $mount } = Component.prototype;
Component.prototype.$mount = function (this: any, ...args: any[]) {
   
let mounted = false;
   
const reactiveRender = () => {
       reaction
.track(() => {
           
if (!mounted) {
               $mount
.apply(this, args);
               mounted
= true;
           
} else {
               
this._watcher.getter.call(this, this);
           
}
       
});
       
return this;
   
};
   
const reaction = new Reaction(`${name}.render()`, reactiveRender);
   dispose
= reaction.getDisposer();
   
return reactiveRender();
};

完整代碼在這里: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ā)送留言,。


① 留言格式:
【投稿】 《 文章標(biāo)題》  文章鏈接

② 示例:
【投稿】《不要自稱是程序員,我十多年的 IT 職場(chǎng)總結(jié)》:http://blog./94148/

③ 最后請(qǐng)附上您的個(gè)人簡(jiǎn)介哈~




覺(jué)得本文對(duì)你有幫助,?請(qǐng)分享給更多人

關(guān)注「前端大全」,,提升前端技能

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多