add rm-n-web

This commit is contained in:
lh_wang
2015-12-07 23:25:43 +08:00
parent 2a489432d6
commit 2244037903
27 changed files with 967 additions and 0 deletions
+647
View File
@@ -0,0 +1,647 @@
<!DOCTYPE html><html>
<head>
<meta charset="utf-8">
<title>H5、React Native、Native应用对比分析</title>
<style type="text/css">
body {
font-family: Helvetica, arial, sans-serif;
font-size: 14px;
line-height: 1.6;
padding-top: 10px;
padding-bottom: 10px;
background-color: white;
padding: 30px; }
body > *:first-child {
margin-top: 0 !important; }
body > *:last-child {
margin-bottom: 0 !important; }
a {
color: #4183C4; }
a.absent {
color: #cc0000; }
a.anchor {
display: block;
padding-left: 30px;
margin-left: -30px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0; }
h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
cursor: text;
position: relative; }
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoMTMuMCAyMDEyMDMwNS5tLjQxNSAyMDEyLzAzLzA1OjIxOjAwOjAwKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM2NjlDQjI4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM2NjlDQjM4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzY2OUNCMDg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzY2OUNCMTg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsQhXeAAAABfSURBVHjaYvz//z8DJYCRUgMYQAbAMBQIAvEqkBQWXI6sHqwHiwG70TTBxGaiWwjCTGgOUgJiF1J8wMRAIUA34B4Q76HUBelAfJYSA0CuMIEaRP8wGIkGMA54bgQIMACAmkXJi0hKJQAAAABJRU5ErkJggg==) no-repeat 10px center;
text-decoration: none; }
h1 tt, h1 code {
font-size: inherit; }
h2 tt, h2 code {
font-size: inherit; }
h3 tt, h3 code {
font-size: inherit; }
h4 tt, h4 code {
font-size: inherit; }
h5 tt, h5 code {
font-size: inherit; }
h6 tt, h6 code {
font-size: inherit; }
h1 {
font-size: 28px;
color: black; }
h2 {
font-size: 24px;
border-bottom: 1px solid #cccccc;
color: black; }
h3 {
font-size: 18px; }
h4 {
font-size: 16px; }
h5 {
font-size: 14px; }
h6 {
color: #777777;
font-size: 14px; }
p, blockquote, ul, ol, dl, li, table, pre {
margin: 15px 0; }
hr {
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;
border: 0 none;
color: #cccccc;
height: 4px;
padding: 0;
}
body > h2:first-child {
margin-top: 0;
padding-top: 0; }
body > h1:first-child {
margin-top: 0;
padding-top: 0; }
body > h1:first-child + h2 {
margin-top: 0;
padding-top: 0; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
margin-top: 0;
padding-top: 0; }
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0; }
h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
margin-top: 0; }
li p.first {
display: inline-block; }
li {
margin: 0; }
ul, ol {
padding-left: 30px; }
ul :first-child, ol :first-child {
margin-top: 0; }
dl {
padding: 0; }
dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px; }
dl dt:first-child {
padding: 0; }
dl dt > :first-child {
margin-top: 0; }
dl dt > :last-child {
margin-bottom: 0; }
dl dd {
margin: 0 0 15px;
padding: 0 15px; }
dl dd > :first-child {
margin-top: 0; }
dl dd > :last-child {
margin-bottom: 0; }
blockquote {
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777; }
blockquote > :first-child {
margin-top: 0; }
blockquote > :last-child {
margin-bottom: 0; }
table {
padding: 0;border-collapse: collapse; }
table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
table tr:nth-child(2n) {
background-color: #f8f8f8; }
table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
table tr th :first-child, table tr td :first-child {
margin-top: 0; }
table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }
img {
max-width: 100%; }
span.frame {
display: block;
overflow: hidden; }
span.frame > span {
border: 1px solid #dddddd;
display: block;
float: left;
overflow: hidden;
margin: 13px 0 0;
padding: 7px;
width: auto; }
span.frame span img {
display: block;
float: left; }
span.frame span span {
clear: both;
color: #333333;
display: block;
padding: 5px 0 0; }
span.align-center {
display: block;
overflow: hidden;
clear: both; }
span.align-center > span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: center; }
span.align-center span img {
margin: 0 auto;
text-align: center; }
span.align-right {
display: block;
overflow: hidden;
clear: both; }
span.align-right > span {
display: block;
overflow: hidden;
margin: 13px 0 0;
text-align: right; }
span.align-right span img {
margin: 0;
text-align: right; }
span.float-left {
display: block;
margin-right: 13px;
overflow: hidden;
float: left; }
span.float-left span {
margin: 13px 0 0; }
span.float-right {
display: block;
margin-left: 13px;
overflow: hidden;
float: right; }
span.float-right > span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: right; }
code, tt {
margin: 0 2px;
padding: 0 5px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px; }
pre code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent; }
.highlight pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px; }
pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px; }
pre code, pre tt {
background-color: transparent;
border: none; }
sup {
font-size: 0.83em;
vertical-align: super;
line-height: 0;
}
* {
-webkit-print-color-adjust: exact;
}
@media screen and (min-width: 914px) {
body {
width: 854px;
margin:0 auto;
}
}
@media print {
table, pre {
page-break-inside: avoid;
}
pre {
word-wrap: break-word;
}
}
</style>
</head>
<body>
<h1 id="toc_0">H5、React Native、Native应用对比分析</h1>
<p>@王利华,vczero </p>
<p>“存在即合理”。凡是存在的,都是合乎规律的。任何新事物的产生总要的它的道理;任何新事物的发展总是有着取代旧事物的能力。React Native来的正是时候,一则是因为H5发展到一定程度的受限;二则是移动市场的迅速崛起强调团队快速响应和迭代;三则是用户的体验被放大,用户要求极致的快感,除非你牛x(例如:12306最近修改手机号需要用户自己发短信接收验证码)。<br>
以下简单的介绍下H5、React Native、Native的含义: </p>
<p>最近三四年间,国内外的前端与全栈开发者社区都在坚持不懈地追寻使用JavaScript与HTML、CSS技术体系开发App内场景的核心工程技术。这种技术,在国内很多公司与团队中,被通称为H5。——童遥 </p>
<p>这段是取自童老师给小二我新书作的序,没有断章取义的意思。很清楚,H5并不是狭义的HTML5新标签和API,而是工程化的“In App” technology。 </p>
<p>iOS/Android ——原生应用(都懂得,不解释)。 </p>
<p>React Native —— React &amp; Native ,应运而生! </p>
<h2 id="toc_1">一、React Native的出现</h2>
<p>React Native的出现,似乎是扛起的反H5的旗子。就像当年Facebook放弃H5,全部转向Native一样。这一点,我们需要认同和保持高度的清醒。那么,React Native是否又是在吞食Native的领地呢?技术的发展,是用户风向标的导向起的作用。任何一门技术的出现,都是当时用户需求的体现。 </p>
<p>我们应该从以下几点看待React Native的出现。</p>
<p>&quot;鉴往知来&quot;——从过去的教训中总结经验,从用户的角度开拓未来<br>
“HTML5差强人意,但是与原生应用相比还是有些差距”——为了更高的追求! 用户体验!<br>
“人才宝贵,快速迭代”——Web开发者相对较多,寻找平衡点<br>
“跨平台!跨平台!跨平台!”——单一技术栈<br>
“xx是世界上最好的语言” ——工程学的范畴,没有最好,只有最适合 </p>
<p>HTML5 <strong>vs</strong> React Native <strong>?</strong> HTML5 <strong>:</strong> React Native<br>
结论(React Native):<br>
1、原生应用的用户体验<br>
2、跨平台特性<br>
3、开发人员单一技术栈<br>
4、上手快,入门容易<br>
5、社区繁荣 </p>
<h2 id="toc_2">二、3款应用效果</h2>
<p><strong>注:以下所有对比均在iOS平台下</strong><br>
<img src="./imgs/hybirdapp.gif" alt=""><br>
<img src="./imgs/ReactDou.gif" alt=""><br>
<img src="./imgs/iOSDou.gif" alt=""><br>
上面3张图片,如果去掉第一张图的“HybirdApp”的字样,是否分得清哪个是React Native开发?哪个是Native应用。<br>
你的第一感觉是什么? </p>
<h2 id="toc_3">三、工程方案</h2>
<p>为了评估3种方案的技术优势和弱势。我们需要开发功能大致相似的App。这里,我们使用了“豆瓣”的API来开发“豆搜”应用。该应用能够搜索“图书”、“音乐”、“电影”。想当年,豆瓣以“图书评论”走红,尤其是12年当红!豆瓣是一个清新文艺的社区,一个“慢公司”。最近有一则网传消息,注意是网传——“传京东投1.5亿美元控股豆瓣”。今天,不聊豆瓣,我们要聊一个工程化的问题。 </p>
<p>我们需要将3款App的功能做到一致,同时需要保持技术要点一致。比如React Native这里使用了TabBar,那么Native我们也必须使用TabBar。简单而言就是:功能一致,组件 &amp; API一致。我们功能如下图所示:<br>
<img src="./imgs/dousou.png" alt=""> </p>
<p><strong>1、H5方案</strong><br>
在H5/Hybird应用中,我们使用AngularJS开发单页webApp,然后将该WebApp内嵌入到iOS WebView中,在iOS代码中,我们使用Navigation稍微控制下跳转。<br>
WebApp地址:http://vczero.github.io/search/html/index.html<br>
WebApp项目地址:https://github.com/vczero/search (很简单的一个项目)<br>
H5/Hybird项目地址:https://github.com/vczero/search_Hybird </p>
<p><strong>2、React Native</strong><br>
在React Native中,封装必要的功能组件。<br>
项目地址:https://github.com/vczero/React-Dou。<br>
项目结构如下图:<br>
<img src="./imgs/rn-1.png" alt=""> </p>
<p><strong>3、Native(iOS)</strong><br>
使用React Native大致相同的组件开发App,不使用任何第三方库,代码布局。<br>
项目地址:https://github.com/vczero/iOS-Dou </p>
<h2 id="toc_4">四、对比分析</h2>
<p>很多时候,新技术的采用最希望看到的是数据,而不是简单说“用户体验棒,开发效率高,维护成本低”。不过,生活中也有这样的同学,知一二而能窥全貌。当然,本人生性胆小,也没有那么多的表哥和隔壁的老王,所以不敢早下定论,不敢太放肆。赵本山在《大笑江湖》中有句名言“May the force be with you”(别太放肆,没什么用)。因此,从以下几个方面做一个简单的对比。 </p>
<p><strong>----------提纲------------</strong></p>
<h4 id="toc_5">1、开发方式</h4>
<p>1)代码结构<br>
2UI布局<br>
3UI截面图<br>
4)路由/Navigation<br>
(5)第三方生态链 </p>
<h4 id="toc_6">2、性能 &amp; 体验</h4>
<p>1)内存<br>
2CPU<br>
3)动画<br>
4)安装包体积<br>
5Big ListView<br>
(6)真机体验 </p>
<h4 id="toc_7">3、更新 &amp; 维护</h4>
<p>1)更新能力<br>
2)维护成本<br>
<strong>----------提纲------------</strong></p>
<h3 id="toc_8">1、开发方式</h3>
<p>很多人说React Native的代码不好看,不好理解。那是因为前端工程师都熟悉了Web的开发方式。怎么解决这个问题呢,可以先看看iOS代码,断定不熟悉iOS的同学心里会默念“一万匹**马奔腾”。那时候,你再看React Native,你会觉得使用React Native开发App是件多么美好的事!OK,我们先来看下三者在开始“一款简单App”的代码结构。<br>
<strong>1)代码结构</strong><br>
H5/Hybird的开发模式,我们需要维护3套代码,两套是Native(iOS/Android)代码,一套是WebApp版本。这里,我们使用AngularJS作为WebApp单页开发框架。如下图所示。<br>
<img src="./imgs/w1.png" alt=""><br>
在React Native中,同样需要关注部分的Native代码,但是大部分还是前端熟悉的JavaScript。在“豆搜”应用中,代码结构如下:<br>
<img src="./imgs/reactnative.png" alt=""><br>
在Native开发中,更加强调Native开发者的能力。平台是:iOS/Android。<br>
<img src="./imgs/ios.png" alt=""><br>
结论:从前端角度而言,React Native跨平台特性,不要开发者深入的了解各平台就能开发一款高效App。同时,语言层面而言,JavaScript运用很广泛,入门门槛相对较低。React Native虽然抛弃了MVC分离实践,但是从业务角度而言,更为合理。一切而言:对前端,对移动领域是利好的消息。 </p>
<p><strong>2UI布局</strong><br>
“面容姣好”,合理的UI却总是跟着时间在变。那么UI布局就不是小事。<br>
Web开发布局目前大多是 DIV + CSS。<br>
React Native的布局方式是Flexbox。 </p>
<pre><code> //JSX
&lt;ScrollView style={styles.flex_1}&gt;
&lt;View style={[styles.search, styles.row]}&gt;
&lt;View style={styles.flex_1}&gt;
&lt;Search placeholder=&quot;请输入图书的名称&quot; onChangeText={this._changeText}/&gt;
&lt;/View&gt;
&lt;TouchableOpacity style={styles.btn} onPress={this._search}&gt;
&lt;Text style={styles.fontFFF}&gt;搜索&lt;/Text&gt;
&lt;/TouchableOpacity&gt;
&lt;/View&gt;
{
this.state.show ?
&lt;ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow}
/&gt;
: Util.loading
}
&lt;/ScrollView&gt;
//样式
var styles = StyleSheet.create({
flex_1:{
flex:1,
marginTop:5
},
search:{
paddingLeft:5,
paddingRight:5,
height:45
},
btn:{
width:50,
backgroundColor:&#39;#0091FF&#39;,
justifyContent:&#39;center&#39;,
alignItems:&#39;center&#39;
},
fontFFF:{
color:&#39;#fff&#39;
},
row:{
flexDirection:&#39;row&#39;
}
}); </code></pre>
<p>而Native布局就有种让你想吐的感觉,尤其是iOS的布局。这里不是指采用xib或者Storyboard,而是单纯的代码,例如添加一个文本: </p>
<pre><code>UILabel *publisher = [[UILabel alloc]init];
publisher.frame = CGRectMake(bookImgWidth + 10, 50, 200, 30);
publisher.textColor = [UIColor colorWithRed:0.400 green:0.400 blue:0.435 alpha:1];
publisher.font = [UIFont fontWithName:@&quot;Heiti TC&quot; size:13];
publisher.text = obj[@&quot;publisher&quot;];
[item addSubview:publisher]; </code></pre>
<p>总结:React Native既综合了Web布局的优势,采用了FlexBox和JSX,又使用了Native原生组件。比如我们使用一个文本组件。<br>
<code>&lt;Text style={{width:100;height:30;backgroundColor:&#39;red&#39;}}&gt;测试&lt;/Text&gt;</code></p>
<p><strong>3UI截面图</strong><br>
<strong>Hybrid方式截面图</strong><br>
<img src="./imgs/h5-1.png" alt=""><br>
可以看到第一层列表页是完整的布局,实际上这就是Web页面;而第二层灰色的是Native的WebView组件。<br>
<strong>iOS UI截面图</strong><br>
<img src="./imgs/ios-1.png" alt=""><br>
<img src="./imgs/ios-2.png" alt=""><br>
可以看到Native页面的组件特别多,即使是列表页,其中某一项都是一个组件(控件)。 </p>
<p>当然,我们就会想,能够完全调用原生组件呢?那样性能是否更好?<br>
<strong>React Native UI截面图</strong><br>
<img src="./imgs/rn-ui-1.png" alt=""><br>
<img src="./imgs/rn-ui-2.png" alt=""><br>
可以清楚的看到React Native调用的全部是Native组件。并且层次更深,因为React Native做了组件的封装。如上图,蓝色边框的就是RCTScrollView组件。 </p>
<p><strong>4)路由/Navigation</strong><br>
在Web单页面应用中,路由由History API实现。<br>
而React Native采用的路由是原生的UINavigationController导航控制器实现。<br>
React Native NavigatorIOS组件封装程度高;Navigator可定制化程度高。<br>
Navigator方法如下: </p>
<pre><code>getCurrentRoutes() - returns the current list of routes
jumpBack() - Jump backward without unmounting the current scene
jumpForward() - Jump forward to the next scene in the route stack
jumpTo(route) - Transition to an existing scene without unmounting
push(route) - Navigate forward to a new scene, squashing any scenes that you could jumpForward to
pop() - Transition back and unmount the current scene
replace(route) - Replace the current scene with a new route
replaceAtIndex(route, index) - Replace a scene as specified by an index
replacePrevious(route) - Replace the previous scene
immediatelyResetRouteStack(routeStack) - Reset every scene with an array of routes
popToRoute(route) - Pop to a particular scene, as specified by its route. All scenes after it will be unmounted
popToTop() - Pop to the first scene in the stack, unmounting every other scene </code></pre>
<p>相对Native而言,这些接口更Native还是很相似的。 </p>
<pre><code>//iOS UINavigationController
//相对Web而言,不用自己去实现路由,并且路由更加清晰
[self.navigationController pushViewController:detail animated:YES];</code></pre>
<p>&quot;豆搜&quot; WebApp路由(基于AngularJS)如下:<br>
<img src="./imgs/webapp-route.png" alt=""> </p>
<p>&quot;豆搜&quot; React Native版本导航如下:<br>
<img src="./imgs/rn-nv.png" alt=""> </p>
<p>&quot;豆搜&quot; iOS版本导航代码如下:<br>
<img src="./imgs/ios-nv.png" alt=""> </p>
<p>总结:React Native封装的导航控制更容易理解。</p>
<p><strong>5)第三方生态链</strong><br>
“我的是我的,你的也是我的。 ”——我不是“疯狂女友”,我是React Native<br>
我们缺少“城市列表”组件,OK,使用JSX封装一个;觉得性能太低,OK,基于React Native方案封装一个原生组件。<br>
这个iOS图表库不错,拿来用呗! =&gt; 完美!<br>
这一切都是基于React Native提供的模块扩展方案。<br>
所以说:iOS第三方库 + 部分JavaScript库 React Native 生态库 </p>
<h3 id="toc_9">2、性能 &amp; 体验</h3>
<p>我们都很关注一款App性能。因此测试和体验App的性能很重要。以下测试,都是基于相同的case。<br>
测试平台:模拟器,iphone6iOS8.4<br>
<strong>1)内存</strong><br>
首先,我们来看下Native应用占用的内存情况。一开始,原生应用启动后,占用内存是20~25M;针对相同的case,跑了2min,结果如下图:<br>
<img src="./imgs/ios-me.png" alt=""><br>
可以看出,峰值是87.9M,均值是72M;内存释放比较及时。 </p>
<p>我们再来看下Hybird App的情况。App已启动,占用内存35~55M;同样,跑了2min以上,结果如下图:<br>
<img src="./imgs/hy-me.png" alt=""><br>
可以看出,峰值在137.9M,因为整个应用在WebView中,内存释放不明显,存在缓存。 </p>
<p>最后,看下React Native的情况。App启动占用内存35~60M,同样跑2min以上,结果如下图:<br>
<img src="./imgs/rn-me.png" alt=""><br>
可以看出,峰值在142M,内存相对释放明显。 </p>
<p>总结:React Native和Web View在简单App上相差不大。二者主要:内存消耗主要是在网页数据上。</p>
<p><strong>2CPU</strong><br>
我们可以看一下Native应用程序CPU的情况,最高值在41%。<br>
<img src="./imgs/ios-cpu.png" alt=""><br>
Hybird App的最高值在30%。<br>
<img src="./imgs/hy-cpu.png" alt=""><br>
React Native的最高值在34%。<br>
<img src="./imgs/rn-cpu.png" alt=""> </p>
<p>总结:CPU使用率大体相近,React Native的占用率低于Native。 </p>
<p><strong>3)动画</strong><br>
React Native提供了Animated API实现动画。简单效果,基本OK。个人觉得React Native不适合做游戏,尤其布局能力。<br>
Native Animation提供UIView动画<br>
H5/Hybird:采用js动画能力<br>
总结:React Native Animated API / 封装Native动画库 可以满足基本需求 </p>
<p><strong>4)安装包体积</strong><br>
<strong>Hybird App:</strong><br>
34(App壳) + 5(HTML) + 125(Angular) + 29(An-route) + 6(min.js) + 4(min.css) = 203 KB。 </p>
<p><strong>React Native:</strong><br>
不含bundle: 843KB<br>
含bundle: 995KB </p>
<p><strong>Native</strong><br>
83KB </p>
<p><strong>React Native框架包大小</strong><br>
843(不含bundle) - 32(Hybird_app空壳,初识项目) = 811KB </p>
<p>相比快速迭代和热更新,比Native多了811KB一点都不重要,我们将图片素材、静态资源线上更新缓存起来即可减少很多体积。<br>
总结:牺牲一点体积,换更大的灵活性!(世界上哪有那么美的事,除非丑,就会想得美,:) )。 </p>
<p><strong>5Big ListView &amp; Scroll 性能</strong><br>
循环列表项500次:
H5页面惨不忍睹<br>
React Native还可以接受<br>
Native 采用UITabView更高效,因为不渲染视图外部分。 </p>
<p><strong>6)真机体验</strong><br>
机型:iphone4siOS7<br>
Native &gt; React Native &gt; Hybird<br>
如果非要给个数字的话,那我个人主观感受是:<br>
Native 95%+ 流畅度<br>
React Native: 85~90% 流畅度<br>
H5/Hybird 70% 流畅度 </p>
<p>总结:NativeReact Native的体验相对而言更流畅。 </p>
<h3 id="toc_10">3、更新 &amp; 维护</h3>
<p><strong>1)更新能力</strong><br>
H5/Hybird: 随时更新,适合做营销页面,目前携程一些BU全部都是H5页面;但是重要的部分还是Native。<br>
React NativeReact Native部分可以热更新,bug及时修复。<br>
Native:随版本更新,尤其iOS审核严格,需要测试过关,否则影响用户。 </p>
<p><strong>2)维护成本</strong><br>
H5/Hybird Web代码 iOS/Android平台支持<br>
React Native:可以一个开发团队 iOS/Android工程师;业务组件颗粒度小,不用把握全局即可修改业务代码。<br>
NativeiOS/Android开发周期长,两个开发团队。 </p>
<p>总结:React Native 统一了开发人员技术栈,代码维护相对容易。 </p>
<h2 id="toc_11">五、综合</h2>
<h4 id="toc_12">1、开发方式</h4>
<p>1)代码结构: React Native更为合理,组件化程度高<br>
2UI布局:Web布局灵活度 &gt; React Native &gt; Native<br>
3UI截面图:React Native使用的是原生组件,<br>
4)路由/NavigationReact Native &amp; Native更胜一筹<br>
5)第三方生态链:Native modules + js modules = React Native modules </p>
<h4 id="toc_13">2、性能 &amp; 体验</h4>
<p>(1)内存:Native最少;因为React Native含有框架,所以相对较高,但是后期平稳后会优于Native。<br>
2CPUReact Native居中。<br>
3)动画:React Native动画需求基本满足。<br>
4)安装包体积:React Native框架打包后,811KB。相比热更新,可以忽略和考虑资源规划。<br>
5Big ListView<br>
6)真机体验:Native &gt;= React Native &gt; H5/Hybrid </p>
<h4 id="toc_14">3、更新 &amp; 维护</h4>
<p>1)更新能力: H5/Hybird &gt; React Native &gt; Native<br>
2)维护成本: H5/Hybird &lt;= React Native &lt; Native </p>
<p>React Native定制难度相比Native有些大;但是具备跨平台能力和热更新能力。<br>
最后<strong>硬广</strong>一下我的书:<br>
<img src="./imgs/book.png" alt=""> </p>
</body>
</html>
@@ -0,0 +1,320 @@
# H5、React Native、Native应用对比分析
@王利华vczero
“存在即合理”。凡是存在的,都是合乎规律的。任何新事物的产生总要的它的道理;任何新事物的发展总是有着取代旧事物的能力。React Native来的正是时候,一则是因为H5发展到一定程度的受限;二则是移动市场的迅速崛起强调团队快速响应和迭代;三则是用户的体验被放大,用户要求极致的快感,除非你牛x(例如:12306最近修改手机号需要用户自己发短信接收验证码)。
以下简单的介绍下H5、React Native、Native的含义:
最近三四年间,国内外的前端与全栈开发者社区都在坚持不懈地追寻使用JavaScript与HTML、CSS技术体系开发App内场景的核心工程技术。这种技术,在国内很多公司与团队中,被通称为H5。——童遥
这段是取自童老师给小二我新书作的序,没有断章取义的意思。很清楚,H5并不是狭义的HTML5新标签和API,而是工程化的“In App” technology。
iOS/Android ——原生应用(都懂得,不解释)。
React Native —— React & Native ,应运而生!
##一、React Native的出现
React Native的出现,似乎是扛起的反H5的旗子。就像当年Facebook放弃H5,全部转向Native一样。这一点,我们需要认同和保持高度的清醒。那么,React Native是否又是在吞食Native的领地呢?技术的发展,是用户风向标的导向起的作用。任何一门技术的出现,都是当时用户需求的体现。
我们应该从以下几点看待React Native的出现。
"鉴往知来"——从过去的教训中总结经验,从用户的角度开拓未来
“HTML5差强人意,但是与原生应用相比还是有些差距”——为了更高的追求! 用户体验!
“人才宝贵,快速迭代”——Web开发者相对较多,寻找平衡点
“跨平台!跨平台!跨平台!”——单一技术栈
“xx是世界上最好的语言” ——工程学的范畴,没有最好,只有最适合
HTML5 **vs** React Native **?** HTML5 **:** React Native
结论(React Native):
1、原生应用的用户体验
2、跨平台特性
3、开发人员单一技术栈
4、上手快,入门容易
5、社区繁荣
##二、3款应用效果
**注:以下所有对比均在iOS平台下**
![](./imgs/hybirdapp.gif)
![](./imgs/ReactDou.gif)
![](./imgs/iOSDou.gif)
上面3张图片,如果去掉第一张图的“HybirdApp”的字样,是否分得清哪个是React Native开发?哪个是Native应用。
你的第一感觉是什么?
##三、工程方案
为了评估3种方案的技术优势和弱势。我们需要开发功能大致相似的App。这里,我们使用了“豆瓣”的API来开发“豆搜”应用。该应用能够搜索“图书”、“音乐”、“电影”。想当年,豆瓣以“图书评论”走红,尤其是12年当红!豆瓣是一个清新文艺的社区,一个“慢公司”。最近有一则网传消息,注意是网传——“传京东投1.5亿美元控股豆瓣”。今天,不聊豆瓣,我们要聊一个工程化的问题。
我们需要将3款App的功能做到一致,同时需要保持技术要点一致。比如React Native这里使用了TabBar,那么Native我们也必须使用TabBar。简单而言就是:功能一致,组件 & API一致。我们功能如下图所示:
![](./imgs/dousou.png)
**1、H5方案**
在H5/Hybird应用中,我们使用AngularJS开发单页webApp,然后将该WebApp内嵌入到iOS WebView中,在iOS代码中,我们使用Navigation稍微控制下跳转。
WebApp地址:http://vczero.github.io/search/html/index.html
WebApp项目地址:https://github.com/vczero/search (很简单的一个项目)
H5/Hybird项目地址:https://github.com/vczero/search_Hybird
**2、React Native**
在React Native中,封装必要的功能组件。
项目地址:https://github.com/vczero/React-Dou。
项目结构如下图:
![](./imgs/rn-1.png)
**3、Native(iOS)**
使用React Native大致相同的组件开发App,不使用任何第三方库,代码布局。
项目地址:https://github.com/vczero/iOS-Dou
##四、对比分析
很多时候,新技术的采用最希望看到的是数据,而不是简单说“用户体验棒,开发效率高,维护成本低”。不过,生活中也有这样的同学,知一二而能窥全貌。当然,本人生性胆小,也没有那么多的表哥和隔壁的老王,所以不敢早下定论,不敢太放肆。赵本山在《大笑江湖》中有句名言“May the force be with you”(别太放肆,没什么用)。因此,从以下几个方面做一个简单的对比。
**----------提纲------------**
####1、开发方式
(1)代码结构
(2)UI布局
(3)UI截面图
4)路由/Navigation
(5)第三方生态链
####2、性能 & 体验
1)内存
2CPU
3)动画
4)安装包体积
5Big ListView
(6)真机体验
####3、更新 & 维护
1)更新能力
2)维护成本
**----------提纲------------**
###1、开发方式
很多人说React Native的代码不好看,不好理解。那是因为前端工程师都熟悉了Web的开发方式。怎么解决这个问题呢,可以先看看iOS代码,断定不熟悉iOS的同学心里会默念“一万匹**马奔腾”。那时候,你再看React Native,你会觉得使用React Native开发App是件多么美好的事!OK,我们先来看下三者在开始“一款简单App”的代码结构。
**1)代码结构**
H5/Hybird的开发模式,我们需要维护3套代码,两套是Native(iOS/Android)代码,一套是WebApp版本。这里,我们使用AngularJS作为WebApp单页开发框架。如下图所示。
![](./imgs/w1.png)
在React Native中,同样需要关注部分的Native代码,但是大部分还是前端熟悉的JavaScript。在“豆搜”应用中,代码结构如下:
![](./imgs/reactnative.png)
在Native开发中,更加强调Native开发者的能力。平台是:iOS/Android。
![](./imgs/ios.png)
结论:从前端角度而言,React Native跨平台特性,不要开发者深入的了解各平台就能开发一款高效App。同时,语言层面而言,JavaScript运用很广泛,入门门槛相对较低。React Native虽然抛弃了MVC分离实践,但是从业务角度而言,更为合理。一切而言:对前端,对移动领域是利好的消息。
**2UI布局**
“面容姣好”,合理的UI却总是跟着时间在变。那么UI布局就不是小事。
Web开发布局目前大多是 DIV + CSS。
React Native的布局方式是Flexbox。
//JSX
<ScrollView style={styles.flex_1}>
<View style={[styles.search, styles.row]}>
<View style={styles.flex_1}>
<Search placeholder="请输入图书的名称" onChangeText={this._changeText}/>
</View>
<TouchableOpacity style={styles.btn} onPress={this._search}>
<Text style={styles.fontFFF}>搜索</Text>
</TouchableOpacity>
</View>
{
this.state.show ?
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow}
/>
: Util.loading
}
</ScrollView>
//样式
var styles = StyleSheet.create({
flex_1:{
flex:1,
marginTop:5
},
search:{
paddingLeft:5,
paddingRight:5,
height:45
},
btn:{
width:50,
backgroundColor:'#0091FF',
justifyContent:'center',
alignItems:'center'
},
fontFFF:{
color:'#fff'
},
row:{
flexDirection:'row'
}
});
而Native布局就有种让你想吐的感觉,尤其是iOS的布局。这里不是指采用xib或者Storyboard,而是单纯的代码,例如添加一个文本:
UILabel *publisher = [[UILabel alloc]init];
publisher.frame = CGRectMake(bookImgWidth + 10, 50, 200, 30);
publisher.textColor = [UIColor colorWithRed:0.400 green:0.400 blue:0.435 alpha:1];
publisher.font = [UIFont fontWithName:@"Heiti TC" size:13];
publisher.text = obj[@"publisher"];
[item addSubview:publisher];
总结:React Native既综合了Web布局的优势,采用了FlexBox和JSX,又使用了Native原生组件。比如我们使用一个文本组件。
`<Text style={{width:100;height:30;backgroundColor:'red'}}>测试</Text>`
**3UI截面图**
**Hybrid方式截面图**
![](./imgs/h5-1.png)
可以看到第一层列表页是完整的布局,实际上这就是Web页面;而第二层灰色的是Native的WebView组件。
**iOS UI截面图**
![](./imgs/ios-1.png)
![](./imgs/ios-2.png)
可以看到Native页面的组件特别多,即使是列表页,其中某一项都是一个组件(控件)。
当然,我们就会想,能够完全调用原生组件呢?那样性能是否更好?
**React Native UI截面图**
![](./imgs/rn-ui-1.png)
![](./imgs/rn-ui-2.png)
可以清楚的看到React Native调用的全部是Native组件。并且层次更深,因为React Native做了组件的封装。如上图,蓝色边框的就是RCTScrollView组件。
**4)路由/Navigation**
在Web单页面应用中,路由由History API实现。
而React Native采用的路由是原生的UINavigationController导航控制器实现。
React Native NavigatorIOS组件封装程度高;Navigator可定制化程度高。
Navigator方法如下:
getCurrentRoutes() - returns the current list of routes
jumpBack() - Jump backward without unmounting the current scene
jumpForward() - Jump forward to the next scene in the route stack
jumpTo(route) - Transition to an existing scene without unmounting
push(route) - Navigate forward to a new scene, squashing any scenes that you could jumpForward to
pop() - Transition back and unmount the current scene
replace(route) - Replace the current scene with a new route
replaceAtIndex(route, index) - Replace a scene as specified by an index
replacePrevious(route) - Replace the previous scene
immediatelyResetRouteStack(routeStack) - Reset every scene with an array of routes
popToRoute(route) - Pop to a particular scene, as specified by its route. All scenes after it will be unmounted
popToTop() - Pop to the first scene in the stack, unmounting every other scene
相对Native而言,这些接口更Native还是很相似的。
//iOS UINavigationController
//相对Web而言,不用自己去实现路由,并且路由更加清晰
[self.navigationController pushViewController:detail animated:YES];
"豆搜" WebApp路由(基于AngularJS)如下:
![](./imgs/webapp-route.png)
"豆搜" React Native版本导航如下:
![](./imgs/rn-nv.png)
"豆搜" iOS版本导航代码如下:
![](./imgs/ios-nv.png)
总结:React Native封装的导航控制更容易理解。
**5)第三方生态链**
“我的是我的,你的也是我的。 ”——我不是“疯狂女友”,我是React Native
我们缺少“城市列表”组件,OK,使用JSX封装一个;觉得性能太低,OK,基于React Native方案封装一个原生组件。
这个iOS图表库不错,拿来用呗! => 完美!
这一切都是基于React Native提供的模块扩展方案。
所以说:iOS第三方库 + 部分JavaScript库 React Native 生态库
###2、性能 & 体验
我们都很关注一款App性能。因此测试和体验App的性能很重要。以下测试,都是基于相同的case。
测试平台:模拟器,iphone6iOS8.4
**1)内存**
首先,我们来看下Native应用占用的内存情况。一开始,原生应用启动后,占用内存是20~25M;针对相同的case,跑了2min,结果如下图:
![](./imgs/ios-me.png)
可以看出,峰值是87.9M,均值是72M;内存释放比较及时。
我们再来看下Hybird App的情况。App已启动,占用内存35~55M;同样,跑了2min以上,结果如下图:
![](./imgs/hy-me.png)
可以看出,峰值在137.9M,因为整个应用在WebView中,内存释放不明显,存在缓存。
最后,看下React Native的情况。App启动占用内存35~60M,同样跑2min以上,结果如下图:
![](./imgs/rn-me.png)
可以看出,峰值在142M,内存相对释放明显。
总结:React Native和Web View在简单App上相差不大。二者主要:内存消耗主要是在网页数据上。
**2CPU**
我们可以看一下Native应用程序CPU的情况,最高值在41%。
![](./imgs/ios-cpu.png)
Hybird App的最高值在30%。
![](./imgs/hy-cpu.png)
React Native的最高值在34%。
![](./imgs/rn-cpu.png)
总结:CPU使用率大体相近,React Native的占用率低于Native。
**3)动画**
React Native提供了Animated API实现动画。简单效果,基本OK。个人觉得React Native不适合做游戏,尤其布局能力。
Native Animation提供UIView动画
H5/Hybird:采用js动画能力
总结:React Native Animated API / 封装Native动画库 可以满足基本需求
**4)安装包体积**
**Hybird App:**
34(App壳) + 5(HTML) + 125(Angular) + 29(An-route) + 6(min.js) + 4(min.css) = 203 KB。
**React Native:**
不含bundle: 843KB
含bundle: 995KB
**Native**
83KB
**React Native框架包大小**
843(不含bundle) - 32(Hybird_app空壳,初识项目) = 811KB
相比快速迭代和热更新,比Native多了811KB一点都不重要,我们将图片素材、静态资源线上更新缓存起来即可减少很多体积。
总结:牺牲一点体积,换更大的灵活性!(世界上哪有那么美的事,除非丑,就会想得美,:) )。
**5Big ListView & Scroll 性能**
循环列表项500次:
H5页面惨不忍睹
React Native还可以接受
Native 采用UITabView更高效,因为不渲染视图外部分。
**6)真机体验**
机型:iphone4siOS7
Native > React Native > Hybird
如果非要给个数字的话,那我个人主观感受是:
Native 95%+ 流畅度
React Native: 85~90% 流畅度
H5/Hybird 70% 流畅度
总结:NativeReact Native的体验相对而言更流畅。
###3、更新 & 维护
**1)更新能力**
H5/Hybird: 随时更新,适合做营销页面,目前携程一些BU全部都是H5页面;但是重要的部分还是Native。
React NativeReact Native部分可以热更新,bug及时修复。
Native:随版本更新,尤其iOS审核严格,需要测试过关,否则影响用户。
**2)维护成本**
H5/Hybird Web代码 iOS/Android平台支持
React Native:可以一个开发团队 iOS/Android工程师;业务组件颗粒度小,不用把握全局即可修改业务代码。
NativeiOS/Android开发周期长,两个开发团队。
总结:React Native 统一了开发人员技术栈,代码维护相对容易。
##五、综合
####1、开发方式
1)代码结构: React Native更为合理,组件化程度高
(2)UI布局:Web布局灵活度 > React Native > Native
3UI截面图:React Native使用的是原生组件,
4)路由/NavigationReact Native & Native更胜一筹
5)第三方生态链:Native modules + js modules = React Native modules
####2、性能 & 体验
(1)内存:Native最少;因为React Native含有框架,所以相对较高,但是后期平稳后会优于Native。
2CPUReact Native居中。
3)动画:React Native动画需求基本满足。
4)安装包体积:React Native框架打包后,811KB。相比热更新,可以忽略和考虑资源规划。
5Big ListView
6)真机体验:Native >= React Native > H5/Hybrid
####3、更新 & 维护
1)更新能力: H5/Hybird > React Native > Native
2)维护成本: H5/Hybird <= React Native < Native
React Native定制难度相比Native有些大;但是具备跨平台能力和热更新能力。
最后**硬广**一下我的书:
![](./imgs/book.png)
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB