【編者按】本文做者爲 14islands 聯合創始人、創新 Web 開發者 David Lindkvist,主要介紹有關混合型應用搭建的方方面面。文章系國內 ITOM 管理平臺 OneAPM 編譯呈現。css
最近,咱們有幸與 Fjord 合做,從零開始爲其用戶打造了一款 HMTL5 混合型應用。html
混合型移動應用(Hybrid apps)能夠藉助多種 web 技術搭建應用,並將其打包爲原生應用(Native apps)以適應於多種移動平臺。前端
在本文中,咱們將分析使用 React 與 Cordova 建立 iOS 與 Android 應用時採用的技術以及面臨的挑戰。react
注意:React Native 在2015年首發。然而,在本項目開始時,React Native Android 版還未發佈,所以咱們沒法使用之。git
混合式移動應用已經不是什麼新鮮事了。同時,它固然也不是編寫全部應用的萬能鑰匙。真正的挑戰在於,達到原始應用的極致體驗,兼具流暢的動畫效果與時尚的用戶界面。github
在過去,使用諸如 Backbone.js 這類更爲傳統的 JavaScript MVC 框架,咱們已經在這一方向上作了屢次冒險嘗試與努力。web
大多數混合式應用項目一開始,都具有快速、響應及時的用戶界面。以後,卻很容易撞上南牆。這一般出如今項目後期,此時,通過數週的努力,項目已經添加了許多的功能,DOM 中的內容也越發豐富。chrome
此時,視圖組件間的關係變得很是難以追蹤,而事件監聽器的循環依賴會致使過多的 DOM 讀寫操做。apache
React 是一個用於建立用戶界面的 JavaScript 函數庫,一般被表述爲 MVC 中的 V(View,視圖)。redux
React 知道根據組件的狀態進行從新渲染,而且保存一個虛擬 DOM 以實現高效的從新渲染。這種方法很是棒,由於咱們寫代碼時就好像在從新渲染整個模板,而實際上 React 只會更新發生過改動的 DOM。
React 與常見框架的最大差異在於,JavaScript 邏輯與 Markup(標記)模板使用 JSX 語法寫在同一個文件中。
class MyTitle extends Component { render() { return ( <header> <h1>Hello World</h1> </header> ) } }
適應這種變化須要一點時間。可是一旦掌握,就能極大地你的提升生產力。
筆者是現代 JavaScript 的狂熱粉絲,偏好使用 Babel 編寫 ES2015 語法。
Mixins 不能與 ES2015 並用,緣由在此。因此,咱們選擇 Higher-order-components(高階組件)來建立功能特徵,而非 mixins:
/** * Exports a higher order component wrapping the component to decorate * @param ComponentToDecorate the component which will be decorated */ export const withDecoratedData = ComponentToDecorate => class extends Component { constructor() { this.state = { data: null }; } componentDidMount() { this.setState({ data: 'Decorated hello!' }); } render() { return <ComponentToDecorate {...this.props} data={this.state.data} />; } }
以後,可使用 ES2016 裝飾器(Decorator)來應用組件。咱們能夠在 Babel 中選擇啓用 ES2016 裝飾器。
import {withDecoratedData} from '...'; // Decorate component using ES7 decorator '@' @withDecoratedData class MyComponent extends Component { render() { return <div>{this.data}</div>; } }
經過這種方式,咱們將視圖組件(View components)與咱們的數據存儲(Data stores)進行了聯結。
對於一個應用而言,視圖層只是表面——表面背後的部分纔是錯綜複雜的境地。React 能夠與大多數其餘框架結合使用,實現對現有數據模型的渲染。然而,大規模 MVC 應用與循環依賴的問題仍舊存在,所以,Facebook 推出了具有「單向數據流」的 Flux 設計模型,以使數據流動更容易預見。
Flux 的實現方式不勝枚舉。在研究了其中一部分案例以後,咱們選定了Alt。
爲了讓應用盡量地接近原生,UI 動畫達到 60 幀每秒,而且沒有閃爍現象是相當重要的。移動端瀏覽器的 JavaScript 性能一直都慢得引人注目,所以,咱們確保只使用純 CSS 動畫與轉換。
最近,React 世界很是熱烈的一個話題是:是否使用行內樣式,也即:在元素樣式屬性內部設置樣式,而不使用 CSS。
實話實說,筆者更喜好 CSS,對行內樣式並不很是感冒。CSS 對重要內容的劃分很是清晰,而做爲 web 開發者,咱們早已熟知如何有效地應用響應式 Web 設計原則(Responsive Web Design principles)來支持不一樣的設備性能與屏幕大小。
行內樣式的最大爭議在於:「狀態」在很大程度上是 JavaScript 關心的問題。不少時候,咱們須要根據動態狀況來改變樣式。不過,你想一下就會發現,經過添加或刪除修飾符類以傳播狀態變更實際上是很完美的方法。
筆者偏好使用 Saas 與通過些微修正的 BEM 類命名慣例編寫大部分樣式。咱們修改了 BEM 塊名使其匹配 CamelCased JavaScript 類名,從而爲每一個組件實現明確的 JavaScript 與 CSS 組合。
class MyComponent { render() { const activeClass = this.props.active ? 'MyComponent--active' : ''; return ( <div className={"MyComponent " + activeClass}> <h1 className="MyComponent__title"> My title </h1> </div> ); } );
對於具有許多狀態修飾符的組件而言,這會顯得有些凌亂與繁瑣。爲此,筆者建立了本身的 bem-helper 以簡化 BEM 類名在 JSX 中的使用。
import BEM from 'bem-helper-js'; class MyComponent { render() { return ( <div className={BEM(this).is('active', this.props.active)}> <h1 className={BEM(this).el('title')}> My title </h1> </div> ); } );
它會自動從 JavaScript 類名中獲取塊名,並認爲 this.props.active is true
爲 true
時,下面的類名就會被渲染:
<div class="MyComponent MyComponent--active"> <h1 class="MyComponent__title">My title</h1> </div>
對習慣了手動添加類或修改樣式的人而言,這部分可能會有點水土不服。現實是,咱們不得不後退一步,讓 React 處理 DOM 的全部更新。
大多數動畫庫都會直接訪問 DOM,所以,請仔細選擇。
幸運的是,React 團隊已經爲咱們提供了 ReactCSSTransitionGroup,能幫解決應用動畫類、在 DOM 中增減動畫元素等常見場景。在咱們的應用中,它有效地處理了頁面轉換。
咱們使用了 Apache Cordova來打包應用,生成 iOS 與 Android 版本。其設置至關簡單直白,而且提供了許多有用的插件,經過一個 JavaScript API 就能實現一些原生功能。
舉個例子,咱們包含了 Statusbar 插件,在運行時改變原生狀態欄的顏色。
從 iOS 8 開始,咱們終於能夠在慣性滾動階段(也即在觸摸中止後持續的滾動動做)設置滾動事件。舊版 UIWebView 並不支持該功能,而 Cordova 默認使用舊版 UIWebView。
對於 iOS 9 用戶期待的 WKWebView 引擎,官方提供了一個 cordova 插件。然而,若是不啓用 CORS,沒法經過 file:// 協議使用 XHR。
對於使用 React 完成此項目,咱們對本身的選擇感到欣慰。可是,咱們仍有一些值得注意的地方,以便在下次作出調整。
優點
缺點
react-router
與 Alt
中都遇到過斷層式的 API 變化。Alt
如今,React Native 的勢頭愈來愈猛,所以值得進一步追蹤。關鍵的不一樣在於,它在 JavaScript 與原生 SDK 之間有一個代理層。它在單獨的線程中運行 JavaScript 代碼,所以在執行其餘操做時還能保證流暢的動畫。此外,經過 Flexbox 方法,React Native 也選擇了行內樣式而非 CSS。據估計,iOS 與 Android 之間超過 85% 的代碼庫能夠實現共享。
本文系 OneAPM 工程師編譯呈現。OneAPM Browser Insight 是一個基於真實用戶的 Web 前端性能監控平臺,可以幫你們定位網站性能瓶頸,網站加速效果可視化;支持瀏覽器、微信、App 瀏覽 HTML 和 HTML5 頁面。想閱讀更多技術文章,請訪問 OneAPM 官方技術博客。
本文轉自 OneAPM 官方博客
原文地址:http://14islands.com/blog/2016/03/03/why-we-chose-react-for-hybrid-app/