为什么选用 React 创建混合型移动应用?
【编者按】本文作者为 14islands 联合创始人、创新 Web 开发者 David Lindkvist,主要介绍有关混合型应用搭建的方方面面。文章系国内 ITOM 管理平台 OneAPM 编译呈现。
最近,我们有幸与 Fjord 合作,从零开始为其用户打造了一款 HMTL5 混合型应用。
混合型移动应用(Hybrid apps)可以借助多种 web 技术搭建应用,并将其打包为原生应用(Native apps)以适应于多种移动平台。
在本文中,我们将分析使用 React 与 Cordova 创建 iOS 与 Android 应用时采用的技术以及面临的挑战。
注意:React Native 在2015年首发。然而,在本项目开始时,React Native Android 版还未发布,因此我们无法使用之。
混合型应用中的挑战
混合式移动应用已经不是什么新鲜事了。同时,它当然也不是编写所有应用的万能钥匙。真正的挑战在于,达到原始应用的极致体验,兼具流畅的动画效果与时尚的用户界面。
在过去,使用诸如 Backbone.js 这类更为传统的 JavaScript MVC 框架,我们已经在这一方向上做了多次冒险尝试与努力。
大多数混合式应用项目一开始,都具备快速、响应及时的用户界面。之后,却很容易撞上南墙。这通常出现在项目后期,此时,经过数周的努力,项目已经添加了许多的功能,DOM 中的内容也愈加丰富。
此时,视图组件间的关系变得非常难以追踪,而事件监听器的循环依赖会导致过多的 DOM 读写操作。
进入 React
React 是一个用于创建用户界面的 JavaScript 函数库,通常被表述为 MVC 中的 V(View,视图)。
React 知道根据组件的状态进行重新渲染,并且保存一个虚拟 DOM 以实现高效的重新渲染。这种方法非常棒,因为我们写代码时就好像在重新渲染整个模板,而实际上 React 只会更新发生过改动的 DOM。
JSX
React 与常见框架的最大差别在于,JavaScript 逻辑与 Markup(标记)模板使用 JSX 语法写在同一个文件中。
class MyTitle extends Component {
render() { return (
<header>
<h1>Hello World</h1>
</header>
)
}
}
适应这种变化需要一点时间。但是一旦掌握,就能极大地你的提高生产力。
Mixins 对决 Composition
笔者是现代 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 设计模型,以使数据流动更容易预见。
为什么选用 React 创建混合型移动应用?从 iOS 8 开始,我们终于可以在惯性滚动阶段(也即在触摸停止后持续的滚动动作)设置滚动事件。旧版 UIWebView 并不支持该功能,而 Cordova 默认使用旧版 UIWebView。
对于 iOS 9 用户期待的 WKWebView 引擎,官方提供了一个 cordova 插件。然而,如果不启用 CORS,无法通过 file:// 协议使用 XHR。
总结
对于使用 React 完成此项目,我们对自己的选择感到欣慰。但是,我们仍有一些值得注意的地方,以便在下次做出调整。
优势
- 渲染性能的提升 —— React 能高效地实现 DOM 的更新
- 简化可重用组件的编写
- 强大的 JSX 语法,实现数据与标记模板的结合
- 一旦体系决策达成,组件开始重用,生产力就能提高
- 避免开发者直接接触 DOM (也即:减少伤害性能的风险)
缺点
- 如果不人为直接修改 DOM,使用 React State 很难实现时间线复杂的动画
- 并非全面的解决方案 ——缺少经验的开发者很难入门。需要选择一个 Router, Flux 库或数据层等等
- 新的 React 版本发布较为频繁,生态系统不够成熟 ——大多数插件的变化比 React 还频繁,而且 API
一直在变化。在本项目中,我们在react-router
与Alt
中都遇到过断层式的 API 变化。Alt
的变化尤其迅速,相关文档也不是最新的。在下一个 React 项目中,我们会专注于 Redux。
接下来去哪儿
现在,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/