上次发布了我的慢牛股票APP之后,有园友反馈有点卡,这个APP是基于Sencha Touch + Cordova开发的,Sencha本身是一个比较重的框架,在Chrome里运行性能还是不错的,但是在Android的WebView里,性能受限于机器的配置,在我的小米2s里表现还行,在小米4s里开起来比较流畅,但是Android机型相比IOS太多样了,Sencha Touch在iOS里表现不错,不过我还没编译iOS版本。

后来我又试着用了下Ionic框架,基于AngularJs开发,这个框架要轻量,在慢牛股票的微信公众号里试着开发了几个页面,感觉很不错,本来想用AngularJs重新做一个APP,但是后来又接触了React Native,试着用了下,React Native的编程体验类似于Sencha Touch,完全的组件化,JSX的语法很有意思,逐步习惯以后,用起来也很顺手。

有兴趣的朋友可以对比下这三个方案,我留下这个三个方案的下载地址:

慢牛股票APP(Sencha Touch+ Cordova)方案

慢牛微信公众号(Ionic方案)

Demo(React Native方案)

截图动画:

React Native相比上面两种,体验更顺畅,当然,原生的应用肯定是比在WebView里体验好的,ReactNative结合了原生开发和Web开发优势,不过,React Native现在对Android的支持不算太好,比如动画。

ReactNative的Flex布局,组件化思想很不错,上手快,不过因为最终显示的是原生,所以还是要多了解下原生的开发,必要时自己做桥接,比如我在做K线图,苦于找不到相关的组件,只有自己桥接了MPAndroidChart。

Demo主要实现了几个我认为比较关键功能:

1、导航

2、列表

3、下拉刷新

4、图表

这几个功能点实现以后,后面的工作就轻松得多了,比如表单提交,第三方登录,设置等等页面。

下面说下这几个点的实现方式,

1、导航

侧滑菜单

熟悉原生开发的同学一看就知道,这是原生的DrawerLayout,通过RN桥接过来, 很滑,很顺,之前用CSS3在WebView里做过侧滑菜单,当然比不上这个啦!

页面切换

利用了RN的Navigator组件,这个组件实现了一个Stack,每次新开页面就是向Stack里Push新的UI导航信息,然后在Render时判断要显示哪个UI组件,这个导航组件会把历史UI移动可视范围之外,利用Opacity把UI设置为透明,然后绝对定位到可视范围之外,返回时,再把历史UI移动可视范围,这样,历史UI的状态还是保持的,这样的导航在Web上也是可以借鉴的。

这个导航还可以设置转场动画,看源代码,确实是实现了不少的动画,包括PushFromRight,FloatFromRight,FadeAndroid等,但是设置后不起作用,只有FadeAndroid有效果,但是动画一闪而过,不顺滑,这里对Android的支持不太好,或者是我的哪里设置不对?

Tab切换

Tab切换做起来比较容易,不过有一点,在页面切换过程中,不要重新Render每个Tab对应的内容,重新Render会清除页面的当前的状态,比如滚动条的位置等,而且性能差,借鉴Navigator,把非焦点的Tab页面移动可视范围之外即可。

Demo中按钮的图标都是矢量的,图标字体的优点不用说了,原生系统也可以用图标字体了,对不喜欢用图片的同学真是一个喜讯,一想到要做那么多图片,要考虑每种分辨率,就头脑哇,这里用了github上的一个开源组件react-native-icons。

贴段代码:

  render: function() {
var navigationView = (
<SideMenu onItemSelected={this.onItemSelected}/>
);
return (
<DrawerLayout
ref="drawerMenu"
drawerWidth={300}
drawerPosition={DrawerLayout.positions.Left}
renderNavigationView={() => navigationView}>
<Navigator
ref='navigator'
debugOverlay={false}
style={styles.appContainer}
configureScene={(route) =>Navigator.SceneConfigs.FloatFromRight}
initialRoute={{name:'main',component:(<TabPanel/>)}}
renderScene={(route, navigator) => {
return (route.component);
}}
/>
</DrawerLayout>
);

2、列表:

Demo里我实现了一个股票的列表,列表拆分成了List组件和ListItem组件,利用React开发,组件化思想很重要,这在之前用Sencha时也有这样的体验。

列表这里没有用ListView组件,是用ScrollVIew包了一个ListTtem的列表,如果数据量比较大,或者比较复杂列表,可以用官方的ListView来做,性能会比较好,每次更新只会更新变化的列表项,也提供了分类,设置表头和表尾等等。

贴段代码:

  createRows:function(){
return this.state.myStockList.map(function (obj) {
return (<StockItem key={obj.code} id={obj.code} data={obj}></StockItem>);
});
},
render: function() {
return (
<SwipeRefreshLayout
ref={(control)=>{this._view=control}}
style={styles.scrollView}
onRefresh={this.reloadData}>
<ScrollView style={{flex:1}}>
{this.createRows()}
</ScrollView>
</SwipeRefreshLayout>
);
}

  

3、下拉刷新:

在github上,有不少的下拉刷新组件,比如;react-native-gifted-listview,但是都是iOS上可以下拉,在Android上有Bug,文档上这样解释:

Pull-to-refresh in Android (tried to implement it but it seems that onResponderRelease event is not catchable yet in Android ListView - React-Native

关于如何在RN里响应手势,我还没怎么了解,后面再动画方面多研究下,因为了解下原生控件的桥接,所有就偷懒了,把原生的SwipeRefreshLayout控件做了桥接,包裹上ScrollVIew,就可以实现下拉刷新了,在JS里响应SwipeRefreshLayout发送的刷新事件,同时开放一个关闭刷新的接口,JS端获取数据更新后,关闭刷新状态。

4、图表

图表这里,我花的时间最多,目前也不是很完善,只不过,可以显示K线了,但是在交互上还是要加强。

之前在Web端做过两次K线图,一个是Sencha的,一个是D3的,用了RN以后,之前的图表都用不上了,也考虑过套个WebView,用D3来做,但是效果肯定不好哇,最后还是学习了原生开发,学习了原生UI的布局,组件的继承架构,学习使用MPAndroidChart组件,如何桥接原生组件等等,收获不小,现在开发一边打开Android Studio,一边打开Sublime。。。

原生的组件,View是所有UI组件的基类,而 ViewGroup是容纳这些组件的容器,其本身也是从View派生出来的,RN提供了两种ViewManager类用来桥接这两类组件,ViewManager管理组件的创建,布局,以及属性设置,事件触发。

贴段代码:

android端(桥接图表代码片段):

public class MPBarLineChartManager extends SimpleViewManager<BarLineChartBase> {
private String CLASS_NAME="MPBarChart"; @Override
public String getName() {
return this.CLASS_NAME;
} @Override
protected BarLineChartBase createViewInstance(ThemedReactContext reactContext) {
BarChart chart=new BarChart(reactContext);
return chart;
} @ReactProp(name="touchEnabled",defaultBoolean = true)
public void setTouchEnabled(BarLineChartBase chart,boolean enable){
chart.setTouchEnabled(enable);
}
   ......
}

js端:

var { requireNativeComponent,PropTypes } = require('react-native');

var iface = {
name: 'BarChart',
propTypes: {
data:PropTypes.object,
touchEnabled:PropTypes.bool,
......
scaleX: PropTypes.number,
scaleY: PropTypes.number,
translateX: PropTypes.number,
translateY: PropTypes.number,
rotation: PropTypes.number,
},
}; module.exports = requireNativeComponent('MPBarChart', iface);

  

这个图表的桥接项目我发布到了github上,目前实现了对柱状图,线形图,以及组合图表的桥接。

https://github.com/hongyin163/react-native-chart-android

有希望用图表的同学可以利用下,要是能继续帮忙增强就更好啦!

学会了桥接原生组件以后,我就陷入了一种模式,只要在RN里实现有难度的,我就想桥接一个原生的Android组件,虽然知道这样不太好,因为如果用了太多原生的组件,后续的迁移麻烦了,当然最好利用官方提供的Android和IOS都支持的组件,最好是用平台无关的方式来做,这里最大的感触是,RN提供了一种途径,让js可以和原生组件交互,业务逻辑写在js里,利用原生组件呈现,如果有原生开发的同学支持,那么利用RN开发就方便多了,提供一致的组件库,一套代码就可以在两个系统上运行了,这样就不仅仅是learn once write anywhere了。

关于性能优化:

1、延迟加载

  如果一次加载太多的组件,RN需要等全部组件渲染完成才显示出来,会有白屏,所有每次加载组件最好少一些,比如先构建页面的框架,框架渲染完成后再加载数据,创建基于数据的组件,或者利用setTimeout延迟加载其他的组件。

2、使用setNativeProps

  React把组件当成状态机,通常是用setState方法,改变组件状态,页面会重新渲染,但是重新渲染性能比较差,setNativeProps可以绕过这个过程,直接修改原生组件的属性,或者调用原生的组件的API,性能就好多了,但是状态同步方面就要多考虑下了。

3、实现shouldComponentUpdate方法

  React在组件渲染时会有个diff算法,如果前后Virtual DOM状态改变,会重新渲染组件,如果实现shouldComponentUpdate方法,返回false,就会避免不必要的diff计算和渲染。

关于React,这篇文章把他的前世今生都说了,写得很好:通往全栈工程师的捷径 —— react

React真是无所不在了,React-DOM,React-Canvas,React-Native,看起来前途无量哇!

最后,大家可以关注慢牛股票的微信公众号:

发送react,可以获取demo的apk文件,安装体验。

这个项目的源码后续会提交到github上,文章写的一般,见谅!欢迎大家评论留名^_^

关于我的兼职创业历程

慢牛系列一:如何抓取股票数据

慢系系列二:前端技术选择

慢牛系列三:React Native实践的更多相关文章

  1. 携程React Native实践

    React Native(下文简称 RN)开源已经一年多时间,国内各大互联网公司都在使用,携程也在今年 5 月份投入资源开始引入,并推广给多个业务团队使用,本文将会分享我们遇到的一些问题以及我们的优化 ...

  2. React Native实践之携程Moles框架

    编者:本文来自携程框架研发部高级经理魏晓军在第二期[携程技术微分享]上的分享,以下为整理后的文字实录.视频回放可点击这里.关注携程技术中心微信公号ctriptech,可获知更多微分享课程信息. 因为支 ...

  3. React Native实践总结一

    一.React的世界观1.通过改变state来改变视图视图不用考虑如何改变自己,把state画出来即可.2.变量不可变通过创建一个新的state来更改state,使得变更可追踪,不容易因为其他部分修改 ...

  4. 慢牛系列四:好玩的React Native

    在上次随笔(系列三)中,我试着用RN实现了一个Demo,感觉很不错,当时遇到的问题这篇文章里基本都解决了,比如导航动画问题,这篇文章里主要介绍RN的动画,学会动画以后,各种小创意都可以实现了^^ 下面 ...

  5. 基于React Native的移动平台研发实践分享

    转载:http://blog.csdn.net/haozhenming/article/details/72772787 本文目录: 一.React Native 已经成为了移动前端技术的趋势 二.基 ...

  6. React Native初探

    前言 很久之前就想研究React Native了,但是一直没有落地的机会,我一直认为一个技术要有落地的场景才有研究的意义,刚好最近迎来了新的APP,在可控的范围内,我们可以在上面做任何想做的事情. P ...

  7. React Native指南汇集了各类react-native学习资源、开源App和组件

    来自:https://github.com/ele828/react-native-guide React Native指南汇集了各类react-native学习资源.开源App和组件 React-N ...

  8. React Native:使用 JavaScript 构建原生应用

    [转载] 本篇为联合翻译,译者:寸志,范洪春,kmokidd,姜天意 数月前,Facebook 对外宣布了正在开发的 React Native 框架,这个框架允许你使用 JavaScript 开发原生 ...

  9. 深入浅出 React Native:使用 JavaScript 构建原生应用

    深入浅出 React Native:使用 JavaScript 构建原生应用 链接:https://zhuanlan.zhihu.com/p/19996445 原文:Introducing React ...

随机推荐

  1. Effective Java 07 Avoid finallizers

    NOTE Never do anything time-critical in a finalizer. Never depend on a finalizer to update critical ...

  2. Effective Java 63 Include failure-capture information in detail message

    Principle To capture the failure, the detail message of an exception should contain the values of al ...

  3. Java主要有那几种文件类型?各自的作用是什么

    1.源代码.java程序员编译的源代码. 2..class  字节码文件 jvm实现跨平台的中间编译文件. 3.jar包 讲字节码文件打包好,便于查找和使用.

  4. 如何解决ajax跨域问题(转)

    由 于此前很少写前端的代码(哈哈,不合格的程序员啊),最近项目中用到json作为系统间交互的手段,自然就伴随着众多ajax请求,随之而来的就是要解决 ajax的跨域问题.本篇将讲述一个小白从遇到跨域不 ...

  5. cookie的读入和读出

    写入cookie中 在mvc的控制器中 HttpCookie GetUserID = new HttpCookie("uID", 要保存的值); GetUserID.Expires ...

  6. 第六篇 :微信公众平台开发实战Java版之如何自定义微信公众号菜单

    我们来了解一下 自定义菜单创建接口: http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_to ...

  7. Sql practice

    employee表 数据准备 use tempdb go if OBJECT_ID('employee') is not null drop table employee ;with employee ...

  8. [转]excel set drop-down values based on vlookup

    本文转自:http://stackoverflow.com/questions/10657811/set-drop-down-values-based-on-vlookup 问: I have a w ...

  9. HTML5性能优化

    HTML5性能优化 在看完这两章内容之后,我意犹未尽,于是乎从网上搜索关键字“Java Web高性能”,在IBM社区找到两篇不错的文章,而让人更意外的是我发现那两篇文章的内容跟<高性能HTML5 ...

  10. 怎么在ZBrush中渲染漫画风格的插画

    创建“漫画插画”的外观和感觉想必一定很有趣吧,但是,获得想要的精确外观有时也会令人相当沮丧,因此了解一些基本原则,创建类似于ZBrush漫画MatCaps的作品很有必要. 若有疑问亦或者想查看具体的视 ...