前端數(shù)據(jù)流哲學(xué)

原文
on 29 Jan 2018
本系列分三部曲:《框架實現(xiàn)》 《框架使用》 與 《數(shù)據(jù)流哲學(xué)》,這三篇是我對數(shù)據(jù)流階段性的總結(jié),正好補(bǔ)充之前過時的文章。

本篇是收官之作 《前端數(shù)據(jù)流哲學(xué)》。

1 引言

寫這篇文章時,很有壓力,如有不妥之處,歡迎指正。

同時,由于這是一篇佛系文章,所以不會得出你應(yīng)該用 某某 框架的結(jié)論,你應(yīng)該當(dāng)作消遣來閱讀。

2 精讀

首先數(shù)據(jù)流管理模式,比較熱門的分為三種。

  • 函數(shù)式、不可變、模式化。典型實現(xiàn):Redux - 簡直是正義的化身。
  • 響應(yīng)式、依賴追蹤。典型實現(xiàn):Mobx。
  • 響應(yīng)式,和樓上區(qū)別是以流的形式實現(xiàn)。典型實現(xiàn):Rxjs、xstream。

當(dāng)然還有第四種模式,裸奔,其實有時候也挺健康的。

數(shù)據(jù)流使用通用的準(zhǔn)則是:副作用隔離、全局與局部狀態(tài)的合理劃分,以上三種數(shù)據(jù)流管理模式都可以實現(xiàn),唯有是否強(qiáng)制的區(qū)別。

2.1 從時間順序說起

一直在思考如何將這三個思維串起來,后來想通了,按照時間順序串起來就非常自然。

暫時略過 Prototype、jquery 時代,為什么略過呢?因為當(dāng)時前端還在野蠻人時代,生存問題都沒有解決,哪還有功夫思考什么數(shù)據(jù)流,設(shè)計模式?前端也是那時候被覺得比后端水的。

好在前端發(fā)展越來越健康,大坑小坑被不斷填上,加上硬件性能的提高,同時需求又越來越復(fù)雜,是時候想想該如何組織代碼了。

最先映入眼簾的是 angular,搬來的 mvvm 思想真是為前端開辟了新的世界,發(fā)現(xiàn)代碼還可以這么寫!雖然 angluar 用起來很重,但 mvvm 帶來的數(shù)據(jù)驅(qū)動思想已經(jīng)越來越深入人心,隨后 react 就突然火起來了。

其實在 react 火起來之前,有一個框架一步到位,進(jìn)入了 react + mobx 時代,對,就是 avalon。avalon 也非常火,但是一個框架要成功,必須天時、地利、人和,當(dāng)時時機(jī)不對,大家處于 angular 疲憊期,大多投入了 react 的懷抱。

可能有些主觀,但我覺得 react 能火起來,主要因為大家認(rèn)為它就是輕量 angular + 繼承了數(shù)據(jù)驅(qū)動思想啊,非常符合時代背景,同時一大波概念被炒得火熱,狀態(tài)驅(qū)動、單向數(shù)據(jù)流等等,基本上用過 angular 的人都跟上了這波節(jié)奏。

雖然 react 內(nèi)置了分形數(shù)據(jù)流管理體系,但總是強(qiáng)調(diào)自己只是 View 層,于是數(shù)據(jù)層增強(qiáng)的框架不斷涌現(xiàn),從 flux、reflux、到 redux。不得不說,react 真的推動了數(shù)據(jù)流管理的獨立,讓我們重新認(rèn)識了數(shù)據(jù)流管理的重要性。

redux 概念太超前了,一步到位強(qiáng)制把副作用隔離掉了,但自己又沒有深入解決帶來的代碼冗余問題,讓我們又愛又恨,于是一部分人把目光轉(zhuǎn)向了 mobx,這個響應(yīng)式數(shù)據(jù)流框架,這個沒有強(qiáng)制分離副作用,所以寫起來很舒服的框架。

當(dāng)然 mobx 如果僅僅是 mvvm 就不會火起來了,畢竟 angular 擺在那。主要是乘上了 react 這趟車,又有很多質(zhì)疑 angular 臟檢測效率的聲音,mobx 也火了起來。當(dāng)然,作為前端的使命是優(yōu)化人機(jī)交互,所以我們都知道,用戶習(xí)慣是最難改變的,直到現(xiàn)在,redux 依然是絕對主流。

mobx 還在小范圍推廣時,另一個更偏門的領(lǐng)域正剛處于萌芽期,就是 rxjs 為代表的框架,和 mobx 公用一個 observable 名詞,大家 mobx 都沒搞清楚,更是很少人會去了解 rxjs。

當(dāng) mobx 逐漸展露頭角時,筆者做了一個類似的庫:dob。主要動機(jī)是 mobx 手感還不夠完美,對于新賦值變量需要用一些 extendObservable 等 api 修飾,正好發(fā)現(xiàn)瀏覽器對 proxy 支持已經(jīng)成熟,因此筆者后來幾乎所有個人項目幾乎都用 dob 替代了 mobx。

這一時期三巨頭之一的 vue 火了起來,成功利用:如果 ”react + mobx 很好用,那為什么不用 vue?“ 的 flag 打動了我。

一直到現(xiàn)在,前端已經(jīng)發(fā)展到可謂五花八門的地步,typescript 打敗 flow 幾乎成為了新的 js,出現(xiàn)了 ember、clojurescript 之后,各大語言也紛紛出了到 js 的編譯實現(xiàn),陸陸續(xù)續(xù)的支持編譯到 webassembly,react 作者都棄坑 js 創(chuàng)造了新語言 reason。

之前寫過一篇初步認(rèn)識 reason 的精讀

能接下來這一套精神洗禮的前端們,已經(jīng)養(yǎng)出內(nèi)心波瀾不驚的功夫,小眾已經(jīng)不會成為跨越舒適區(qū)的門檻,再學(xué)個 rxjs 算啥呢?(開個玩笑,rxjs 社區(qū)不乏深耕多年的巨匠)所以最近 rxjs 又被炒的火熱。

所以,從時間順序來看,我們可以從 redux - mobx - rxjs 的順序解讀這三個框架。

2.2 redux 帶來了什么

redux 是強(qiáng)制使用全局 store 的框架,盡管無數(shù)人在嘗試將其做到局部化。

當(dāng)然,一方面是由于時代責(zé)任,那時需要一個全局狀態(tài)管理工具,彌補(bǔ) react 局部數(shù)據(jù)流的不足。最重要的原因,是 redux 擁有一套幾乎潔癖般完美的定位,就是要清晰、可回溯。

幾乎一切都是為了這兩個詞準(zhǔn)備的。第一步就要從分離副作用下手,因為副作用是阻礙代碼清晰、以及無法回溯的第一道障礙,所以 action + reducer 概念閃亮登場,完美解決了副作用問題??赡苁菂⒖剂?koa 中間件的設(shè)計思路,redux middleware 將 action 對接到 reducer 的黑盒的控制權(quán)暴露給了開發(fā)者。

由 redux middleware 源碼閱讀引發(fā)的函數(shù)式熱,可能又拉近了開發(fā)者對 rxjs 的好感。同時高階函數(shù)概念也在中間件源碼中體現(xiàn),幾乎是為 react 高階組件做鋪墊。

社區(qū)出現(xiàn)了很多方案對 redux 異步做支持,從 redux-thunk 到 redux-saga,redux 帶來的異步隔離思想也逐漸深入人心。同時基于此的一套高階封裝框架也層出不窮,建議用一個就好,比如 dva

第二步就是解決阻礙回溯的“對象引用”機(jī)制,將 immutable 這套龐大思想搬到了前端。這下所有狀態(tài)都不會被修改,基于此的 redux-dev-tools “時光機(jī)” 功能讓人印象深刻。

Immutable 具體實現(xiàn)可以參考筆者之前寫的一篇精讀:精讀 Immutable 結(jié)構(gòu)共享

當(dāng)然,由于很像事件機(jī)制的 dispatch 導(dǎo)致了 redux 對 ts 支持比較繁瑣,所以對 redux 的項目,維護(hù)的時候需要頻繁使用全文搜索,以及至少在兩個文件間來回跳躍。

2.3 mobx 帶來了什么

mobx 是一個非常靈活的 TFRP 框架,是 FRP 的一個分支,將 FRP 做到了透明化,也可以說是自動化。

從函數(shù)式(FP),到 FRP,再到 TFRP,之間只是拓展關(guān)系,并不意味著單詞越長越好。

之前說過了,由于大家對 redux 的疲勞,讓 mobx 得以迅速壯大,不過現(xiàn)在要從另一個角度分析。

mobx 帶來的概念從某種角度看,與 rxjs 很像,比如,都說自己的 observable 有多神奇。那么 observable 到底是啥呢?

可以把 observable 理解為信號源,每當(dāng)信號變化時,函數(shù)流會自動執(zhí)行,并輸出結(jié)果,對前端而言,最終會使視圖刷新。這就是數(shù)據(jù)驅(qū)動視圖。然而 mobx 是 TFRP 框架,每當(dāng)變量變化時,都會自動觸發(fā)數(shù)據(jù)源的 dispatch,而且各視圖也是自動訂閱各數(shù)據(jù)源的,我們稱為依賴追蹤,或者叫自動依賴綁定。

筆者到現(xiàn)在還是認(rèn)為,TFRP 是最高效的開發(fā)方式,自動訂閱 + 自動發(fā)布,沒什么比這個更高效了。

但是這種模式有一個隱患,它引發(fā)了副作用對純函數(shù)的污染,就像 redux 把 action 與 reducer 合起來了一樣。同時,對 props 的直接修改,也會導(dǎo)致與 react 對 props 的不可變定義沖突。因此 mobx 后來給出了 action 解決方案,解決了與 react props 的沖突,但是沒有解決副作用未強(qiáng)制分離的問題。

筆者認(rèn)為,副作用與 mutable 是兩件事,關(guān)于 mutable 與副作用的關(guān)系,后文會有說明。也就是 mobx 沒有解決副作用問題,不代表 TFRP 無法分離副作用,而且 mutable 也不一定與 可回溯 沖突,比如 mobx-state-tree,就通過 mutable 的方式,完成了與 redux 的對接。

前端對數(shù)據(jù)流的探索還在繼續(xù),mobx 先提供了一套獨有機(jī)制,后又與 redux 找到結(jié)合點,前端探索的腳步從未停止。

2.4 rxjs 帶來了什么

rxjs 是 FRP 的另一個分支,是基于 Event Stream 的,所以從對 view 的輔助作用來說,相比 mobx,顯得不是那么智能,但是對數(shù)據(jù)源的定義,和 TFRP 有著本質(zhì)的區(qū)別,似的 rxjs 這類框架幾乎可以將任何事件轉(zhuǎn)成數(shù)據(jù)源。

同時,rxjs 其對數(shù)據(jù)流處理能力非常強(qiáng)大,當(dāng)我們把前端的一切都轉(zhuǎn)為數(shù)據(jù)源后,剩下的一切都由無所不能的 rxjs 做數(shù)據(jù)轉(zhuǎn)換,你會發(fā)現(xiàn),副作用已經(jīng)在數(shù)據(jù)源轉(zhuǎn)換這一層完全隔離了,接下來會進(jìn)入一個美妙的純函數(shù)世界,最后輸出到 dom driver 渲染,如果再加上虛擬 dom 的點綴,那豈不是。。豈不就是 cyclejs 嗎?

多提一句,rxjs 對數(shù)據(jù)流純函數(shù)的抽象能力非常強(qiáng)大,因此前端主要工作在于抽一個工具,將諸如事件、請求、推送等等副作用都轉(zhuǎn)化為數(shù)據(jù)源。cyclejs 就是這樣一個框架:提供了一套上述的工具庫,與 dom 對接增加了虛擬 dom 能力。

rxjs 給前端數(shù)據(jù)流管理方案帶來了全新的視角,它的概念由 mobx 引發(fā),但解題思路卻與 redux 相似。

rxjs 帶來了兩種新的開發(fā)方式,第一種是類似 cyclejs,將一切前端副作用轉(zhuǎn)化為數(shù)據(jù)源,直接對接到 dom。另一種是類似 redux-observable,將 rxjs 數(shù)據(jù)流處理能力融合到已有數(shù)據(jù)流框架中,

redux-observable 將 action 與 reducer 改造為 stream 模式,對 action 中副作用行為,比如發(fā)請求,也提供了封裝好的函數(shù)轉(zhuǎn)化為數(shù)據(jù)源,因此,將 redux middleware 中的副作用,轉(zhuǎn)移到了數(shù)據(jù)源轉(zhuǎn)換做成中,讓 action 保持純函數(shù),同時增強(qiáng)了原本就是純函數(shù)的 reducer 的數(shù)據(jù)處理能力,非常棒。

如果說 redux-saga 解決了異步,那么 redux-observable 就是解決了副作用,同時贈送了 rxjs 數(shù)據(jù)處理能力。

回頭看一下 mobx,發(fā)現(xiàn) rxjs 與 mobx 都有對 redux 的增強(qiáng)方案,前端數(shù)據(jù)流的發(fā)展就是在不斷交融。

我們不但在時間線上,將 redux、mobx、rxjs 串了起來,還發(fā)現(xiàn)了他們內(nèi)在的關(guān)聯(lián),這三個思想像一張網(wǎng),復(fù)雜的交織在一起。

2.5 可以串起來些什么了

我們發(fā)現(xiàn),redux 和 rxjs 完全隔離了副作用,是因為他們有一個共性,那就是對前端副作用的抽象。

redux 通過在 action 做副作用,將副作用隔離在 reducer 之外,使 reducer 成為了純函數(shù)。

rxjs 將副作用先轉(zhuǎn)化為數(shù)據(jù)源,將副作用隔離在管道流處理之外。

唯獨 mobx,缺少了對副作用抽象這一層,所以導(dǎo)致了代碼寫的比 redux 和 rxjs 更爽,但副作用與純函數(shù)混雜在一起,因此與函數(shù)式無緣。

有人會說,mobx 直接 mutable 改變對象也是導(dǎo)致副作用的原因,筆者認(rèn)為是,也不是,看如下代碼:

obj.a = 1

這段代碼在 js 中鐵定是 mutable 的?不一定,同樣在 c++ 這些可以重載運(yùn)算符的語言中也不一定了,setter 語法不一定會修改原有對象,比如可以通過 Object.defineProperty 來重寫 obj 對象的 setter 事件。

由此我們可以開一個腦洞,通過運(yùn)算符重載,讓 mutable 方式得到 immutable 的結(jié)果。在筆者博客 Redux 使用可變數(shù)據(jù)結(jié)構(gòu) 有說明原理和用法,而且 mobx 作者 mweststrate 是這么反駁那些吐槽 mobx 缺少 redux 歷史回溯能力的聲音的:

autorun(() => {
  snapshots.push(Object.assign({}, obj))
})

思路很簡單,在對象有改動時,保存一張快照,雖然性能可能有問題。這種簡單的想法開了個好頭,其實只要在框架層稍作改造,便可以實現(xiàn) mutable 到 immutable 的轉(zhuǎn)換。

比如 mobx 作者的新作:immer 通過 proxy 元編程能力,將 setter 重寫為 Object.assign() 實現(xiàn) mutable 到 immutable 的轉(zhuǎn)換。

筆者的 dob-redux 也通過 proxy,調(diào)用 Immutablejs.set() 實現(xiàn) mutable 到 immutable 的轉(zhuǎn)換。

組件需要數(shù)據(jù)流嗎

真的是太看場景了。首先,業(yè)務(wù)場景的組件適合綁定全局?jǐn)?shù)據(jù)流,業(yè)務(wù)無關(guān)的通用組件不適合綁定全局?jǐn)?shù)據(jù)流。同時,對于復(fù)雜的通用組件,為了更好的內(nèi)部通信,可以綁定支持分形的數(shù)據(jù)流。

然而,如果數(shù)據(jù)流指的是 rxjs 對數(shù)據(jù)處理的過程,那么任何需要數(shù)據(jù)復(fù)雜處理的場合,都適合使用 rxjs 進(jìn)行數(shù)據(jù)計算。同時,如果數(shù)據(jù)流指的是對副作用的歸類,那任何副作用都可以利用 rxjs 轉(zhuǎn)成一個數(shù)據(jù)源歸一化。當(dāng)然也可以把副作用封裝成事件,或者 promise。

對于副作用歸一化,筆者認(rèn)為更適合使用 rxjs 來做,首先事件機(jī)制與 rxjs 很像,另外 promise 只能返回一次,而且之后 resolve reject 兩種狀態(tài),而 Observable 可以返回多次,而且沒有內(nèi)置的狀態(tài),所以可以更加靈活的表示狀態(tài)。

所以對于各類業(yè)務(wù)場景,可以先從人力、項目重要程度、后續(xù)維護(hù)成本等外部條件考慮,再根據(jù)具體組件在項目中使用場景,比如是否與業(yè)務(wù)綁定來確定是否使用,以及怎么使用數(shù)據(jù)流。

可能在不遠(yuǎn)的未來,布局和樣式工作會被 AI 取代,但是數(shù)據(jù)驅(qū)動下數(shù)據(jù)流選型應(yīng)該比較難以被 AI 取代。

再次理解 react + mobx 不如用 vue 這句話

首先這句話很有道理,也很有分量,不過筆者今天將從一個全新的角度思考。

經(jīng)過前面的探討,可以發(fā)現(xiàn),現(xiàn)在前端開發(fā)過程分為三個部分:副作用隔離 -> 數(shù)據(jù)流驅(qū)動 -> 視圖渲染。

先看視圖渲染,不論是 jsx、或 template,都是相同的,可以互相轉(zhuǎn)化的。

再看副作用隔離,一般來說框架也不解決這個問題,所以不管是 react/ag/vue + redux/mobx/rxjs 任何一種組合,最終你都不是靠前面的框架解決的,而是利用后面的 redux/mobx/rxjs 來解決。

最后看數(shù)據(jù)流驅(qū)動,不同框架內(nèi)置的方式不同。react 內(nèi)置的是類 redux 的方式,vue/angular 內(nèi)置的是類 mobx 的方式,cyclejs 內(nèi)置了 rxjs。

這么來看,react + redux 是最自然的,react + mobx 就像 vue + redux 一樣,看上去不是很自然。也就是 react + mobx 別扭的地方僅在于數(shù)據(jù)流驅(qū)動方式不同。對于視圖渲染、副作用隔離,這兩個因素不受任何組合的影響。

就數(shù)據(jù)流驅(qū)動問題來看,我們可以站在更高層面思考,比如將 react/vue/angular 的語法視為三種 DSL 規(guī)范,那其實可以用一種通用的 DSL 將其描述,并轉(zhuǎn)換對應(yīng)的 DSL 對接不同框架(阿里內(nèi)部已經(jīng)有這種實現(xiàn)了)。而這個 DSL 對框架內(nèi)置數(shù)據(jù)流處理過程也可以屏蔽,舉個例子:

<button onClick={() => {
  setState(() => {
    data: {
      name: 'nick'
    }
  })
}}>
  {data.name}
</button>

如果我們將上面的通用 jsx 代碼轉(zhuǎn)換為通用 DSL 時,會使用通用的方式描述結(jié)構(gòu)以及方法,而轉(zhuǎn)化為具體 react/vue/angluar 代碼時,就會轉(zhuǎn)化為對應(yīng)內(nèi)置數(shù)據(jù)流方案的實現(xiàn)。

所以其實內(nèi)置數(shù)據(jù)流是什么風(fēng)格,在有了上層抽象后,是可以忽略的,我們甚至可以利用 proxy,將 mutable 的代碼轉(zhuǎn)換到 react 時,改成 immutable 模式,轉(zhuǎn)到 vue 時,保持 mutable 形式。

對框架封裝的抽象度越高,框架之間差異就越小,漸漸的,我們會從框架名稱的討論中解放,演變成對框架 + 數(shù)據(jù)流哪種組合更加合適的思考。

3 總結(jié)

最近梳理了一下 gaea-editor - 筆者做的一個 web designer,重新思考了其中插件機(jī)制,拿出來講一講。

首先大體說明一下,這個編輯器使用 dob 作為數(shù)據(jù)流,通過 react context 共享數(shù)據(jù),寫法和 mobx 很像,不過這不是重點,重點是插件拓展機(jī)制也深度使用了數(shù)據(jù)流。

什么是插件拓展機(jī)制?比如像 VScode 這些編輯器,都擁有強(qiáng)大的拓展能力,開發(fā)者想要添加一個功能,可以不用學(xué)習(xí)其深奧的框架內(nèi)容,而是讀一下簡單明了的插件文檔,使用插件完成想要功能的開發(fā)。解耦的很美好,不過重點是插件的能力是否強(qiáng)大,插件可以觸及內(nèi)核哪些功能、拿到哪些信息、擁有哪些能力?

筆者的想法比較激進(jìn),為了讓插件擁有最大能力,這個 web designer 所有內(nèi)核代碼都是用插件寫的,除了調(diào)用插件的部分。所以插件可以隨意訪問和修改內(nèi)核中任何數(shù)據(jù),包括 UI。

讓 UI 擁有通用能力比較容易,gaea-editor 使用了插槽方式渲染 UI,也就是任何插件只要提供一個名字,就能嵌入到申明了對應(yīng)名字的 UI 插槽中,而插件自己也可以申明任意數(shù)量的插槽,內(nèi)核中也有幾個內(nèi)置的插槽。這樣插件的 UI 能力極強(qiáng),任何 UI 都可以被新的插件替代掉,只要申明相同的名字即可。

剩下一半就是數(shù)據(jù)能力,筆者使用了依賴注入,將所有內(nèi)核、插件的 store、action 全量注入到每一個插件中:

@Connect
class CustomPlugin extends React.PureComponent {
  render() {
    // this.props.Actions, this.props.Stores
  }
}

同時,每個插件可以申明自己的 store,程序初始化時會合并所有插件的 store 到內(nèi)存中。因此插件幾乎可以做任何事,重寫一套內(nèi)核也沒有問題,那么做做拓展更是輕松。

其實這有點像 webpack 等插件的機(jī)制:

export default (context) => {}

每次申明插件,都可以從函數(shù)中拿到傳來的數(shù)據(jù),那么通過數(shù)據(jù)流的 Connect 能力,將數(shù)據(jù)注入到組件,也是一種強(qiáng)大的插件開發(fā)方式。

更多思考

通過上面插件機(jī)制的例子會發(fā)現(xiàn),數(shù)據(jù)流不僅定義了數(shù)據(jù)處理方式、副作用隔離,同時依賴注入也在數(shù)據(jù)流功能列表之中,前端數(shù)據(jù)流是個很寬泛的概念,功能很多。

redux、mobx、rxjs 都擁有獨特的數(shù)據(jù)處理、副作用隔離方式,同時對應(yīng)的框架 redux-react、mobx-react、cyclejs 都補(bǔ)充了各種方式的依賴注入,完成了與前端框架的銜接。正是應(yīng)為他們紛紛將內(nèi)核能力抽象了出來,才讓 redux+rxjs mobx+rxjs 這些組合成為了可能。

未來甚至?xí)Q生一種完全無數(shù)據(jù)管理能力的框架,只做純 view 層,內(nèi)核原生對接 redux、mobx、rxjs 也不是沒有可能,因為框架自帶的數(shù)據(jù)流與這些數(shù)據(jù)流框架比起來,太弱了。

react stateless-component 就是一種嘗試,不過現(xiàn)在這種純 view 層組件配合數(shù)據(jù)流框架的方式還比較小眾。

純 view 層不代表沒有數(shù)據(jù)流管理功能,比如 props 的透傳,更新機(jī)制,都可以是內(nèi)置的。

不過筆者認(rèn)為,未來的框架可能會朝著 view 與數(shù)據(jù)流完全隔離的方式演化,這樣不但根本上解決了框架 + 數(shù)據(jù)流選擇之爭,還可以讓框架更專注于解決 view 層的問題。

從有到無

HTML5 有兩個有意思的標(biāo)簽:details, summary。通過組合,可以達(dá)到 details 默認(rèn)隱藏,點擊 summary 可以 toggle 控制 details 下內(nèi)容的效果:

<details>
  <summary>標(biāo)題</summary> 
  <p>內(nèi)容</p> 
</details>

更是可以通過 css 覆蓋,完全實現(xiàn) collapse 組件的效果。

當(dāng)然就 collapse 組件來說,因為其內(nèi)部維持了狀態(tài),所以控制折疊面板的 打開/關(guān)閉 狀態(tài),而 HTML5 的 details 也通過瀏覽器自身內(nèi)部狀態(tài),對開發(fā)者只暴露 css。

在未來,瀏覽器甚至可能提供更多的原生上層組件,而組件內(nèi)部狀態(tài)越來越不需要開發(fā)者關(guān)心,甚至,不需要開發(fā)者再引用任何一個第三方通用組件,HTML 提供足夠多的基礎(chǔ)組件,開發(fā)者只需要引用 css 就能實現(xiàn)組件庫更換,似乎回到了 bootstrap 時代。

有人會說,具有業(yè)務(wù)含義的再上層組件怎么提供?別忘了 HTML components,這個規(guī)范配合瀏覽器實現(xiàn)了大量原生組件后,可能變得異常光彩奪目,DSL 再也不需要了,HTML 本身就是一套通用的 DSL,框架更不需要了,瀏覽器內(nèi)置了一套框架。

插一句題外話,所有組件都通過 html components 開發(fā),就真正意義上實現(xiàn)了抹平框架,未來不需要前端框架,不需要 react 到 vue 的相互轉(zhuǎn)化,組件加載速度提高一個檔次,動態(tài)組件 load 可能只需要動態(tài)加載 css,也不用擔(dān)心不同環(huán)境/框架下開發(fā)的組件無法共存。前端發(fā)展總是在進(jìn)兩步退一步,不要形成思維定式,每隔一段時間,需要重新審視下舊的技術(shù)。

話題拉回來,從瀏覽器實現(xiàn)的 details 標(biāo)簽來看,內(nèi)部一定有狀態(tài)機(jī)制,假如這套狀態(tài)機(jī)制可以提供給開發(fā)者,那數(shù)據(jù)流的 數(shù)據(jù)處理、副作用隔離、依賴注入 可能都是瀏覽器幫我們做了,redux 和 mobx 會立刻失去優(yōu)勢,未來潛力最大的可能是擁有強(qiáng)大純函數(shù)數(shù)據(jù)流處理能力的 rxjs。

當(dāng)然在 2018 年,redux 和 mobx 依然會保持強(qiáng)大的活力,就算在未來瀏覽器內(nèi)置的數(shù)據(jù)流機(jī)制,rxjs 可能也不適合大規(guī)模團(tuán)隊合作,尤其在現(xiàn)在有許多非前端崗位兼職前端的情況下。

就像現(xiàn)在 facebook、google 的模式一樣,在未來的更多年內(nèi),前后端,甚至 dba 與算法崗位職能融合,每個人都是全棧時,可能 rxjs 會在更大范圍被使用。

縱觀前端歷史,數(shù)據(jù)流框架從無到有,但在未來極有可能從有變到無,前端數(shù)據(jù)流框架消失了,但前端數(shù)據(jù)流思想永遠(yuǎn)保留了下來,變得無處不在。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容