介紹一項讓 React 能夠與 Vue 抗衡的技術

好吧,我認可我是標題黨。React 明明如日中天,把它與 Vue 倒過來,給 Vue 加點東西或可與 React 抗衡。不過,這兩年 Vue 乾的正是這事,不斷加東西,不斷優化,按它現有發展速度超越 React 或在情理之中。若是我有一項技術,能讓 React 克服短板、維持長板,Vue 再怎麼追都趕不上呢?javascript

這項技術就是 Shadow Widget,開源的,入口在這裏(github/rewgt)css

 

1. 若無來處便剩歸途

前些天讀過一篇文章,某專家推薦新手入門人工智能最便捷的途徑,不是仿 AlphaGo 開發個程序,而是找到十年前、二十年前人工智能領域關鍵的幾篇論文,把經典文章吃透,而後再去編程。知道了每項技術怎麼來的,解決了什麼問題,又引起了什麼新問題,把一步步演化過程梳理清楚,就能更清晰的把握下一步工做重點與發展方向。html

反推一下 Windows 的來處吧,從 Win3.一、3.2,Win9五、9八、NT 等,一路疊代到如今的 Window10,若是你是比爾.蓋茲,會不會以爲砍掉一半版本 Windows 將發展更好?尤爲近十年推出那麼多殘次品,在 XP 以後,只有 Win7 與 Win10 產生市場價值。這家公司純粹爲推產品而推產品,忘記爲何作產品了,在 IE 產品線這點表現更明顯。前端

fuck IE

在 IE6 以後,大版本有十數個,只有最近推的 Edge 纔回歸正常(等後人總結歷史,無疑會把 IE6 與 Edge 之間的全部 IE 都稱爲垃圾)。對前端開發人員而言,他面對的瀏覽器就兩類,一類叫 IE,另外一類叫其它,MS 自擼了這麼多年,才突然發現跟他身後一塊兒擼的小弟一個都沒了,整整齊齊排到另外一條隊列,並且合夥把本身落下老遠。因而收起老大心態,老老實實作一款「不隔路」的,叫 Edge 的產品。IE 產品團隊未必全都低能,但產品經理絕對例外,從根子上他就沒想明白開發這款產品給誰用,怎麼用,沒了初心,就剩末路了,當全部前端開者都心生厭惡乃至鄙視時,再強勢的市場地位也是白搭。java

那麼,如今前端開發的初心是什麼?是由 DOM 描述器疊加 JS 控制嗎?顯然不是,早期的網頁很簡單,前端開發的任務也很純粹,用 "html + CSS" 描述界面節點,再用 JS 搞點交互控制,就夠用了。如今狀況有變,前端開發應歸類到完整的、具有徹底能力的 GUI 開發。上世紀末,咱們只把相似 Delphi、MFC、WxWidget 之類的開發稱爲界面開發,前端實施的是網頁開發(相關工具並不叫做 GUI 工具),網頁能力與常規 GUI 差出一大截,爲了彌補能力缺失,因而有出各類插件技術發展出來,好比藉助 java、ActionScript 工具等補上短板。如今,有了 HTML五、CSS3,不借助插件的網頁表現力與平臺原生的 GUI 差距不大了,網站開發更適合看做 GUI 開發,加上移動端設備興起,java 與 ActionScript 再也不有效,尤爲出現 Angular、React、Vue 等新興框架後,大型、複雜的前端開發也能輕鬆應對了,「網頁開發」 應迴歸到常規的 「GUI 開發」 主線上來。GUI 開發更初始,更反映本質需求,瀏覽器出現以前已普遍存在。node

Web framework history

2. 網頁可視化開發趨勢

我用 Delphi 作開發早於用 MFC,Delphi 1.1 剛推出就開始用了,當時 MFC 表明了先進生產力,當我熟悉 Delphi 後,改用 MFC 感受異常痛苦。以後 20 年裏我還用過 VB、WxWidget、PythonTk、Qt、C#、XCode 等 GUI 開發工具,總體觀感是:Delphi 確立的開發方式還是最佳,儘管 Delphi 日漸式微,以致如今不多有人提到它了。但那套 RAD (Rapid Application Develop) 開發模式並未過期,一些新興工具,如 XCode,仍繼承它的作法。react

拿 MFC 與 Delphi 對比前端開發工具,像 MFC 的有一堆,凡沒支持所見即所得可視化設計的,像 Angular、Vue 等都應納入此類,像 Delphi 的幾乎沒有,該補課了,Shadow Widget 是例外,但 Shadow Widget 新近推出,應用效果有待檢驗。git

通用的可視化設計,在前端開發中那麼難出現,我猜主要有兩點緣由:github

  1. 爲網頁提供可視化設計的難度高於傳統 GUI 工具,如 Delpphi、Qt、XCode 等
    傳統 GUI 工具只需爲有限元素提供可視化設計封裝,網頁的可視化則不一樣,它面對各類標籤,量大並且富於變化,增長控制屬性很隨意,擴展也隨意,使用大量自定義標籤是現代框架的重要設計手段。標籤化描述相似於命令行,把海量命令行轉爲可視化設計並不容易。編程

  2. 受限於網頁技術發展水平
    在 Html5 與 Css3 出現以前,原生網頁的表現力頗有限,相比 Qt 所能實現 GUI 效果,相差了一大截。Html5 與 Css3 補上這個短板後,javascript 不適合模塊化、工程化、規模化開發的短板突顯出來,因而業界有 ES六、ES七、Babel 等新生事物冒出,藉助 nodeJS 整合工具鏈,這個進程現已完成,儘管還留點缺陷。同時,Angular、React、Vue 等框架也在新興的前端技術條件下,不斷嘗試最優開發方法,主流框架還都在快速疊代、演化中,MVC、MVVM、FRP 等方法不斷推陳出新,最優的、達成共識的開發方法還沒有造成。

總之,網頁開發正從當前的陳述方式(書寫 HTML 的 tag 標籤,或使用 JSX 定義界面),逐步走向 陳述與可視化並重 的方式。Shadow Widget 順應了這個趨勢,時機正好,若過早發展,估計會像 QML 那樣淪爲無名,當 JS 語言與框架還在快速變化中,嘗試規範並簡化界面的表達形式是徒勞的。

儘管 React 核心庫只在虛擬 DOM 層面提供方案,但它強烈的函數式風格,影響了其工具鏈上各工具的方向性選擇,都對標到函數式開發上來了。這也致使 React 工具的易用性要比 Vue 差出很多,Vue 基於 MVVM 框架,很契合可視形態(也就是頁面跑起來的樣子)的界面開發方式。另外,當 Vue 也引入虛擬 DOM、store、action 等機制後,React 引覺得傲的功能 Vue 裏慢慢都會有,Vue 趕超 React 彷佛指日可待。

上述提法,基於我對前端開發場景的一個認知:趨向靜態的 MVVM 優於趨向動態的 FRP 架構,固然,FRP 自有優點,若是二選一,寧選 MVVM,若是二者都可選,也應以 MVVM 爲主,FRP 爲輔,至少總體設計時如此(二者實際上處於不一樣層次,爲主、爲輔是相對的,下文還有介紹)。

讓網頁支持所見即得的可視化設計,是 MVVM 框架的最高形態,之前沒有相似工具,主要由於技術作不到。Shadow Widget 在設計之初就着手解決可視化設計的問題,立足點高於 Vue,這種優點正如 Vue 比 React 晚推出,能夠大量借鑑 React 同樣,Shadow Widget 也晚推出,能夠吸收 Vue 優勢。不一樣的是,支持可視化需在頂層作設計,改造已定形的 MVVM 框架來支持可視化並不容易。

3. 迴歸本原之一:jQuery 用得爽如何繼續爽下去?

考慮一種應用場景,用戶要開發一個網頁,主體是展現一些文字與圖片,也有少許交互控制的內容,好比輸入反饋信息後點 「提交」 按鈕。若是用 jQuery 開發,代碼不足百行,若是用 React 會很麻煩,工具鏈很繁重,遠沒有用 jQuery 那麼簡單直接,或乾脆什麼庫都不用,什麼框架都不用,裸寫 JS 都簡化不少。

現實開發中,此類場景常常遇到,產品開發並不總在處理複雜頁面的。雖然說裸寫 JS 能減小麻煩,但常常不受控,有時與別人對接或合入別人的代碼,別人用了 React,你不得不被同化;有時開始時簡單,後來需求變了,網頁越作越複雜,你不得不往框架遷移;還有時,爲方便項目統一維護,上頭要求全部 JS 都往 React 裏塞。

Shadow Widget 強調實用重於形式,它推薦的開發方式是:能用 ES5 編程儘可能用 ES5,用 <script> 標籤把 reactshadow-widget 庫導入進來後,在網頁文件中直接寫 JS 腳本就能作開發。這就像以往 jQuery 編程那樣,用 <script> 導入庫,而後直接用 ES5 編碼。

若是按 React 官方推薦的方式,定義一個 Component 類樣式以下:

class RedFlower extends React.Component {
  constructor(props) {
    // ...
  }
  
  componentDidMount() {
    // ...
  }

  render() {
    // ...
  }
}

若是這麼開啓編程之旅,你就被 React 工具鏈綁架了,小紅帽套上,你不要也得要。

獎你一朵小紅花
不要也得要

Shadow Widget 內部一概改用 React.createClass() 引入 Component 行爲定義,由於直接支持 ES5 規格的代碼,沒必要經 Babel 轉譯,這看上去很土,卻很實用。例如:

main['.body.top.p.tool'] = {
  getDefaultProps: function() {
    var props = T.Button.getDefaultProps();
    // props.attr = value;
    return props;
  },

  getInitialState: function() {
    var state = this._getInitialState(this);
    // ...
    return state;
  },

  $onClick: function(event) {
    alert('clicked');
  },
};

不過 Shadow Widget 不排斥用 ES6 編程,自定義一個 Component 類能夠用 ES6+ 語法,只需從已有的,符合 Shadow Widget 規格的 Component 類開始繼承,不能從 React.Component 繼承,例如:

class MyButton_ extends T.Button_ {
  constructor(name,desc) {
    super(name,desc);
  }
  
  getDefaultProps() {
    var props = super.getDefaultProps();
    // props.attr = value;
    return props;
  }

  getInitialState() {
    var state = super.getInitialState();
    // ...
    return state;
  }

  $onClick: function(event) {
    alert('clicked');
  }
}

// convert to React class
var AbstractButton = new MyButton_();
var MyButton = AbstractButton._createClass({});
var jsx = <MyButton>test</MyButton>;

var MyButton2 = AbstractButton._createClass( {
  $onClick: function(event) {
    alert('another onClick');
  }
});
var jsx2 = <MyButton2>test2</MyButton2>;

注意到了嗎?上面代碼沒有直接定義 React class,而是加了一層抽象,AbstractButton 是類的類,用 AbstractButton._createClass() 才實例化成 React class。這麼設計,一方面讓 Component 定義正常使用類繼承,另外一方面讓 Component 的界面表現能有選擇的與行爲定義分離,這是在線支持可視化設計的基礎。

4. 迴歸本原之二:不要一上來就讓我陷入抽象!

撇開網頁設計的專有屬性,任何產品開發都要求設計者先考慮用戶怎麼操做,UI 可視化設計過程,也就是定義用戶需求,並把需求往各層設計分解的過程。因此,界面設計是承上啓下的,它應在編碼以前進行,而不是與編碼混雜同步進行,也不是先寫底層代碼,被動的跟隨變化。對於網頁產品更如此,只要不拿網頁開發命令行程序,網頁就是用戶交互操做最直接的媒介。

React 的 JSX 設計方式讓 GUI 設計混合於編碼之中,未保證界面設計的第一性,其主流的 Flux 工具,均強化了數據傳遞如何設計,讓開發者一上來就思考 action 與 store 怎麼設計,而非界面該如何表現。react-route 更爲極端,它鼓勵你們第一步就思考路由,並以此爲提綱展開各項設計,很不人性。Shadow Widget 第一步就要求考慮界面如何表現,並且只在 UI 設計想清楚後再作別的,而後第二步、第三步才考慮數據如何流動、路由如何規劃等,讓 「網頁開發」 迴歸常規 GUI 開發,這纔是正確的姿式。

Vue 易用性賽過 React,很大程度上是由於 MVVM 中的 component 定義與界面表現一一對應,思考很直接。Shadow Widget 則在 MVVM 基礎上加強了即時可視化能力,以所見即所得的方式讓每次閉環疊代的週期縮短,從而讓開發更加敏捷。

拿具體例子解釋上面意思,比方設計一個播放器,有兩種思考方式,第一種,先理清界面交互方式,是否爲了區分鏈接播放與只播放單個音頻,在界面設計兩個播放按鈕,仍是共用一個按鈕(但另加 「是否連續播放」 選項框)?要不要提供暫停按鈕?暫停按鈕是否與播放按鈕併合?第二種思考方式,先肯定用到哪些數據,數據又由哪些 action 驅動,好比要有播放器與播放列表,要定義一個狀態屬性表示暫停或播放中,驅動它變動的 action 有 play, pause, stop 等,還要有一個 「是否連續播放」 屬性,與播放列表一塊兒做爲 payload 附在 play action 上傳遞,播放列表還有增刪改 action,等等。

雖然這兩種思考方式都能達到目的,但從嚴格意義上講,選擇哪種是工做方法對錯的問題,而不是我的風格喜愛的問題。第二種思考方式錯誤在於,「容易偏離需求」 與 「喪失需求分解層次感」,至於 「設計過程欠直觀」 仍是次要的、附帶的。容易偏離需求,好比你爲手錶設計播放器,增長的 「是否連續播放」 選項在界面擺不下,若採用第二種思考方式你很容易忽略這個限制。另外,設計過程是有層次的,自頂向下,由粗入細,需求在各層設計逐步分解,上一層操做方式變化會影響下一層如何設計,若是以數據與 action 爲思考出發點,很容易喪失設計層次感,沒有前置思考界面如何交互,上層如何表現對下層設計的影響也容易被延後思考,甚至扭曲了。

5. 引入 MVVM 並與 Flux 框架協做共存

支持可視化設計的第一步,分離 Component 的界面表現與它的行爲定義,即,在設計態咱們在可視設計器中只展現各 Componet 的可視特徵,而不捆綁它的行爲定義(好比 onClick 事件處理),當產品正式運行時,即,非設計態,各 Component 的行爲定義將在初始化時正常捆綁。Shadow Widget 可視設計的輸出是 「轉義標籤」,保存在當前 *.html 文件中,行爲定義則記錄在 js 文件,這二者相似於 Delphi 的 *.frm 界面定義文件與 *.pas 代碼實現文件。

可視化設計第二步,引入 MVVM 架構

MVVM

Shadow Widget 內部採用 Object.defineProperty() 定義雙源屬性,使得相似 comp.duals.attr = value 的賦值語句能自動觸發預設的 setter 函數。以後再對雙源屬性增長偵聽機制,凡被 listen 的 duals.attr,其值變化會按事件方式被訂閱,進而構造聯動觸發機制。

雙源屬性解決了相似 Vue 中數據雙向綁定的需求,ViewModel 創建在數據流自動傳遞基礎上,Shadow Widget 爲此還增長 $if, $elif, $else, $for 等控制指令,讓界面能按特定規則由數據驅動自動生成,再有 trigger 機制、可計算屬性、棧式調用空間等設計,讓數據傳遞、組裝、條件控制等變得靈活、強大。總之,Shadow Widget 的 MVVM 機制與 Vue 基本相似,限於篇幅本文不展開介紹。

支持可視化設計第三步,讓 MVVM 架構與 Flux 單向數據流協同工做

這裏只扼要解釋,之後還會專門寫文章介紹。在 Shadow Widget 中,各 Component 若未按編程方式參與行爲定製(專指在 main[sPath] 定義投影類,或用 idSetter[sId] 實現定義),就視做 View 節點,凡參與定製的 Component 視做 ViewModel,各 ViewModel 節點使用的 props.attrduals.attr 屬於 Model。這是一種經過擴展虛擬 DOM 節點的能力而實現的機制,並不直接干擾 Flux 單向數據流機制,有影響的是,咱們要採用多 Store 而非單 Store 機制,另外還要把 Component 節點複用爲 Store 節點,用雙源屬性支持 action 分發(dispatch)與觸發(trigger)。

可視化設計與 MVVM 架構密不可分,React 技術棧與 Flux 機制密不可分,它的 Functional React Programming 理念與可視化編程能夠兼容,MVVM 主導上層些、粗粒度的設計,細粒度與橫向聯繫由 FRP 主導。二者交匯點就是參與行爲定製的、可視的 Component 節點,也就是 ViewModel 節點。雙源屬性同時支撐 MVVM 框架與 FRP 框架,兩種框架分別主管 「縱向嵌套定義界面」 與 「橫向消息聯繫」,處理過程很是天然

6. 工程化開發的必然需求:技術分層與人員分工

各個主流前端框架都使用 NodeJS 集結工具鏈,它們都考慮了規範化、工程化開發的需求,都用 NPM 包管理各層庫的依賴關係,但它們廣泛沒爲技術分層帶來的人員分工,在框架層面提供有效支持。

不管 Angular,React,仍是 Vue,都是重框架,輕不起來,快速入門不能算輕,要以真正能開發產品、獨立解決問題爲準,學透這些框架都要花很多時間。回想十年前,前端開發是一個實習生簡單翻翻參考書就能作的,如今要有一年以上經驗纔算入門,並且,不一樣素質的人產出代碼的質量相差很遠。前端開發該對人員分層管理了,這是既是工程化開發的需求,也是產品開發趨於複雜化必然提出的要求。

Shadow Widget 所構築的技術體系,將前端開發劃分爲兩大部分:構件(Widget)開發與界面(GUI)開發。前者要求分發者具有完整技能,後者則只需簡單技能,即:會用 html、css、javascript,掌握 react 入門知識,藉助界面可視化設計器很快就能勝任工做。也就是說,咱們預想前端開發人員至少可分兩類,一類是入門級的,實習生水準,他主要工做是拿別人已開發好的構件搭積木,另外一類是高級工程師,他爲前一類開發者開發構件。

相信全部老闆都喜歡這麼分工,能省錢!專業化分工後,總體開發效率與質量都會提高。

(本文完)

相關文章
相關標籤/搜索