为什么选用 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 创建混合型移动应用?

Flux 的实现方式不胜枚举。在研究了其中一部分案例之后,我们选定了Alt。

UI 样式与动画

为了让应用尽可能地接近原生,UI 动画达到 60 帧每秒,并且没有闪烁现象是至关重要的。移动端浏览器的 JavaScript 性能一直都慢得引人注目,因此,我们确保只使用纯 CSS 动画与转换。

行内样式 对战 CSS

最近,React 世界非常热烈的一个话题是:是否使用行内样式,也即:在元素样式属性内部设置样式,而不使用 CSS。

实话实说,笔者更喜爱 CSS,对行内样式并不非常感冒。CSS 对重要内容的划分非常清晰,而作为 web 开发者,我们早已熟知如何有效地应用响应式 Web 设计原则(Responsive Web Design principles)来支持不同的设备性能与屏幕大小。

行内样式的最大争议在于:“状态”在很大程度上是 JavaScript 关心的问题。很多时候,我们需要根据动态情况来改变样式。不过,你想一下就会发现,通过添加或删除修饰符类以传播状态变动其实是很完美的方法。

BEM 钟爱 React

笔者偏好使用 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 truetrue 时,下面的类名就会被渲染:

<div class="MyComponent MyComponent--active">  <h1 class="MyComponent__title">My title</h1></div>

通过 React 实现动画

对习惯了手动添加类或修改样式的人而言,这部分可能会有点水土不服。现实是,我们不得不后退一步,让 React 处理 DOM 的所有更新。

大多数动画库都会直接访问 DOM,因此,请仔细选择。

幸运的是,React 团队已经为我们提供了 ReactCSSTransitionGroup,能帮解决应用动画类、在 DOM 中增减动画元素等常见场景。在我们的应用中,它有效地处理了页面转换。

收尾

我们使用了 Apache Cordova来打包应用,生成 iOS 与 Android 版本。其设置相当简单直白,并且提供了许多有用的插件,通过一个 JavaScript API 就能实现一些原生功能。

举个例子,我们包含了 Statusbar 插件,在运行时改变原生状态栏的颜色。

为什么选用 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-routerAlt 中都遇到过断层式的 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/

转载于:https://www.cnblogs.com/oneapm/p/5477299.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/430558.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中除了跟数据相关的知识_Java的基本数据类型及知识介绍

一、基本数据类型&#xff1a;byte&#xff1a;Java中最小的数据类型&#xff0c;在内存中占8位(bit)&#xff0c;即1个字节&#xff0c;取值范围-128~127&#xff0c;默认值0short&#xff1a;短整型&#xff0c;在内存中占16位&#xff0c;即2个字节&#xff0c;取值范围-327…

java null错误事例_java – aspectJ示例中的nullpointer异常

我试图实现我们的stackoverflow成员在这里Logging entry, exit and exceptions for methods in java using aspects给出的建议之一.由于这本身就是不同的问题,再次在这里发布.我试图搜索,但看起来不同的版本有不同的方式,并无法在网上找出一个例子.我尝试了以下简单示例,因为我…

python中减法运算函数_OpenCV-Python图像的减法运算cv2.subtract函数详解以及和矩阵减...

OpenCV-Python图像的减法运算cv2.subtract函数详解以及和矩阵减OpenCV-Python图像的减法运算cv2.subtract函数详解以及和矩阵减法的差异对比? ? 前往老猿Python博文目录 ?在《OpenCV-Python图像的加法运算cv2.add函数详解》详细介绍了图像的加法运算&#xff0c;有加法就有减…

数据访问......单条件查询与多条件查询

一. 将数据库数据访问封装成类 <?php class DB {public $host "localhost"; //服务器地址public $uid "root"; //用户名public $pwd "123"; //密码//执行SQL语句,返回相应结果的方法//$sql代表要执行的SQL语句,$type代表…

java keytool nginx_java 自签名证书转 nginx 所需证书

下面个将介绍怎样利用 jdk keytool 生成自签名证书&#xff0c;然后使用 JKS2PFX 工具将证书转换成 pem 格式。详细步骤如下&#xff1a;(1)先试用 jdk 自带的 keytool 工具生成证书&#xff0c;如下&#xff1a;C:\Users\Administrator\Desktop\jks2pfx>keytool -genkey -v…

《浪潮之巅》读后感

《浪潮之巅》读后感 一开始看了几个公司的故事&#xff0c;感觉有点不够详细、扎实&#xff0c;以为这只是又一本讲述硅谷、讲述那些高科技行业明星的揽财书&#xff0c;但随着阅读的深入发现自己错了&#xff0c;也庆幸自己错了。强烈推荐那些非IT人士也看一看这本书。就…

java implements interface_java接口(interface)与现实(implements)

package com.sadhu;import java.util.*;/**接口接口中不能有字段所有的方法都是公共的可以定义常量接口是多继承的&#xff0c;一个类可以继承多个接口。接口中不能有实现的方法。可以认为是纯的抽象类。接口不能被实例化&#xff0c;但是可以声明一个接口类型的变量*/public c…

java集合类分析-hashset

一、 HashSet概述&#xff1a; HashSet实现Set接口&#xff0c;由哈希表&#xff08;实际上是一个HashMap实例&#xff09;支持。它不保证set 的迭代顺序&#xff1b;特别是它不保证该顺序恒久不变。此类允许使用null元素。 二、 HashSet的实现&#xff1a; 对于HashSet而言&…

php功能大马加密乱码,php大马加密工具 phpTrace:奇虎360开源的PHP脚”的相关知识...

phpTrace&#xff1a;奇虎360开源的PHP脚本分析工具问题&#xff1a;phpTrace&#xff1a;奇虎360开源的PHP脚本分析工具回答&#xff1a;phpTrace是奇虎 360开源的一款和分析PHP脚本的工具。如果开发者用过strace的话&#xff0c;则可能很容易想到phpTrace到底实现了什么样的功…

站立会议 2

这是我们的第二次人员集中&#xff0c;主要是讨论一下接下来的一些工作安排&#xff0c;还有讨论一下在准备过程中出现的一些问题&#xff01; 项目进展&#xff1a; 今天的会议中&#xff0c;我们讨论了我们的项目进展&#xff0c;结果是&#xff1a;我们都已经找到了小球还有…

网吧java安装路径,java环境变量配置

windows xp下配置JDK环境变量&#xff1a;1.安装JDK&#xff0c;安装过程中可以自定义安装目录等信息&#xff0c;例如我们选择安装目录为D:/java/jdk1.5.0_08&#xff1b;2.安装完成后&#xff0c;右击“我的电脑”&#xff0c;点击“属性”&#xff1b;3.选择“高级”选项卡&…

转为win64后, MS的lib问题

> 正在创建库 C:\Users\Administrator\Desktop\branch-Unicode-156\\Temp\Link\PointCloudMeasure\x64\Debug\PointCloudMeasure.lib 和对象 C:\Users\Administrator\Desktop\branch-Unicode-156\\Temp\Link\PointCloudMeasure\x64\Debug\PointCloudMeasure.exp1>vtkXM…

php redis 搜索,PHP+Redis有序集合(zset)实现博客园阅读排行榜功能

许多网站都有排行榜的功能&#xff0c;比如球员人气榜单、阅读排行榜&#xff0c;对于一些小网站&#xff0c;通过查数据库就能实现排行榜的功能&#xff0c;但是对于稍微有点用户量而且还是实时排名的网站&#xff0c;使用一些关系型数据库如(MySQL、Oracle)等来实现就有点力不…

iOS 开发疑难杂症(01)

搜了好多博客&#xff0c;技术网站&#xff0c;答案都不统一&#xff0c;今天偶然发现一个解决方案&#xff1a;这个问题一般是重复导入&#xff0c;使用include的问题&#xff0c;不过iOS一般不用include&#xff0c;所以这个不是正解&#xff0c;还有就是预编译文件&#xff…

php 游标 上移,jQuery点击input使光标移动到最后或指定位置

你要知道面对一个 处女座的 需求者&#xff0c; focus()是远远不够的。 比如说“我点进去的时候光标要在最后&#xff0c;这样我就不用再把光标移动到最后去添加东西了。” oh&#xff0c;让我先撞下墙。 我们需要扩展jQuery: //光标放在最后 $("#文本框ID").textFoc…

nginx 代理

nginx 代理&#xff1a; server { listen 80; server_name yiitest yiitest.com; error_log /var/log/www/yiitest_error.log; access_log /data/logs/nginx/wslm_access.log; root /home/bear/www/yiitest; # 如果全部的请求都代理到别的服务器上了&#xff0c;就可以不用写这…

在java中goto是意思,关于Java中的goto语句

自学Java遇到的问题1goto语句的问题1.1 背景2.1 尝试3.1 总结goto语句的问题今天是我自学Java第4天&#xff0c;开始写博客记录学习中遇到的问题。给后来者一些借鉴&#xff0c;也给自己以后回过来在看这些问题提供资料。1.1 背景我是先自学过一段时间C&#xff0c;然后隔了很长…

cJONS序列化工具解读二(数据解析)

cJSON数据解析 关于数据解析部分&#xff0c;其实这个解析就是个自动机&#xff0c;通过递归或者解析栈进行实现数据的解析 /* Utility to jump whitespace and cr/lf *///用于跳过ascii小于32的空白字符 static const char *skip(const char *in) { while (in && *in…

php备投程序,php投票小程序

PHP投票小程序&#xff0c;防超时&#xff0c;防IP限制1.[代码][PHP]代码//欢迎访问back.zhizhi123.com//参考博文http://www.zhizhi123.com/?p126set_time_limit(0);//防止超时function toupiao($i){$proxy array(182.48.116.51:8080,110.177.63.191:9999,221.10.40.238:80,…

登录注册实现(服务器数据)

1 <?xml version"1.0" encoding"utf-8"?>2 <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"3 android:layout_width"fill_parent"4 android:layout_height"fill_parent"5 …