慢牛系列三:React Native实践
上次发布了我的慢牛股票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实践的更多相关文章
- 携程React Native实践
React Native(下文简称 RN)开源已经一年多时间,国内各大互联网公司都在使用,携程也在今年 5 月份投入资源开始引入,并推广给多个业务团队使用,本文将会分享我们遇到的一些问题以及我们的优化 ...
- React Native实践之携程Moles框架
编者:本文来自携程框架研发部高级经理魏晓军在第二期[携程技术微分享]上的分享,以下为整理后的文字实录.视频回放可点击这里.关注携程技术中心微信公号ctriptech,可获知更多微分享课程信息. 因为支 ...
- React Native实践总结一
一.React的世界观1.通过改变state来改变视图视图不用考虑如何改变自己,把state画出来即可.2.变量不可变通过创建一个新的state来更改state,使得变更可追踪,不容易因为其他部分修改 ...
- 慢牛系列四:好玩的React Native
在上次随笔(系列三)中,我试着用RN实现了一个Demo,感觉很不错,当时遇到的问题这篇文章里基本都解决了,比如导航动画问题,这篇文章里主要介绍RN的动画,学会动画以后,各种小创意都可以实现了^^ 下面 ...
- 基于React Native的移动平台研发实践分享
转载:http://blog.csdn.net/haozhenming/article/details/72772787 本文目录: 一.React Native 已经成为了移动前端技术的趋势 二.基 ...
- React Native初探
前言 很久之前就想研究React Native了,但是一直没有落地的机会,我一直认为一个技术要有落地的场景才有研究的意义,刚好最近迎来了新的APP,在可控的范围内,我们可以在上面做任何想做的事情. P ...
- React Native指南汇集了各类react-native学习资源、开源App和组件
来自:https://github.com/ele828/react-native-guide React Native指南汇集了各类react-native学习资源.开源App和组件 React-N ...
- React Native:使用 JavaScript 构建原生应用
[转载] 本篇为联合翻译,译者:寸志,范洪春,kmokidd,姜天意 数月前,Facebook 对外宣布了正在开发的 React Native 框架,这个框架允许你使用 JavaScript 开发原生 ...
- 深入浅出 React Native:使用 JavaScript 构建原生应用
深入浅出 React Native:使用 JavaScript 构建原生应用 链接:https://zhuanlan.zhihu.com/p/19996445 原文:Introducing React ...
随机推荐
- 用js获取当前页面的url的相关信息方法
当前页面对应的URL的一些属性: ( http://bbs.xxx.net/forum.php?mod=viewthread&tid=2709692&page=1&extra= ...
- saltstack通过salt.client执行命令(转)
利用saltstack的salt.client模块可以在python的命令行下或者python脚本里执行相应的salt命令 master端想要执行类似 salt '*' cmd.run 'uptime ...
- 读书笔记——Windows核心编程(2)比较字符串
1. CompareString 以符合用户语言习惯的方式,EX版本使用UNICODE int CompareString( __in LCID Locale, __in DWORD dwCmpFla ...
- Centos Ping不通外网
安装完成Vm,Centos6.5,设置了网络: 1.VM虚拟网络,采用桥接模式. 2.Centos里各种 设置ifcfg-eth0中的GETWAY,ADDIP等等 vim /etc/sysconfig ...
- html跳转倒计时
<html> <head> <title>出错啦~~~</title> <link href="css/login1.css" ...
- C++ new(1)
如果找工作的同学看一些面试的书,我相信都会遇到这样的题:sizeof 不是函数,然后举出一堆的理由来证明 sizeof 不是函数.在这里,和 sizeof 类似,new 和 delete 也不是函数, ...
- uva 122 trees on the level——yhx
题目如下:Given a sequence of binary trees, you are to write a program that prints a level-order traversa ...
- Android Sdk 和ADT Eclipse安装配置步骤
由于我们之前下载的jdk版本是1.6的,所以后面的andriod sdk等版本需要相对应.安装文件我都放在云盘里面,需要的可以下载 一:如果单独安装每一个软件,先期需要下载的软件包如下: 1.JDK ...
- unix基本命令日记
鉴于命令经常忘记,网站文章鱼龙混杂,很多不适合自己,现在记录方便自己查看.每个人的基础不同,需要合适的文章也不一样. 用户管理 useradd 功能说明:建立用户帐号. 语 法:useradd [-m ...
- Linux 删除文件中某一行的方法
如果有一个abc.txt文件,内容是: aaa bbb ccc ddd eee fff 如果要删除aaa,那么脚本可以这样写: sed -i '/aaa/d' abc.txt 如果删除的是一个变量的值 ...