【编者按】本文做者为 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/