一、选择RN的优势与劣势
优势:
1,提升产品迭代速度,需求/交互评审不再需要与多端开发同时沟通,避免多端开发理解不一致,而且呢,某一个功能模块开发测试只需要交付一个人负责,测试也是;
2,提升开发效率,统一使用flex布局,使用最新语法(比如现在的ES6语法),特别是拓展操作符,灵活方便;
3,提供团队成员个人发展的更多选择,促进大前端成员技术交流,促进全栈工程师的形成;
4,提供热更新HotFix,当然这个在android原生端也比较容易实现;
劣势:
1,对跨平台并不是100%兼容的,部分功能表现在android与ios上面不一致,很难通过UI与产品的走查,需要另外用原生支持。而且对动画比较丰富和页面支持也比较困难,耗时长效果差,对;
2,开发时需要开两个IDE,对电脑性能要求高,环境切换用同时切换RN与原生的环境,较为繁琐。
二、RN与原生交互
2.1,原生跳转RN:
public Bundle getLaunchOptions() {
Bundle bundle = new Bundle();
bundle.putString("params", new Gson().toJson(activityParams));
return bundle;
}
2.2,RN处理接收原生传递的参数:
let params = this.(props.navigation.state.)params.pageParams.shopName
2.3,RN之间页面的跳转:
this.navigate(RouterPaths.SerachCarBrand, {
finish: (model) => this.finishChooseModel(model)
});
回调方法其传过来的方法:
this.params.finish(item)
2.4,RN接收RN传递的参数:
this.shopName = this.params && this.params.pageParams
2.5,RN页面返回:
navigateBack = (routerKey = '') => {
if (StringUtils.isNoEmpty(routerKey)) {
const backAction = NavigationActions.back({key: routerKey,})
this.props.navigation.dispatch(backAction);
} else {
this.props.navigation.goBack()
}
}
2.6,RN调用原生的方法
NativeModules.commModule.getNativeStore(constants.isEnglish, value => {
this.setState({isEnglish: (value == 1) || (value == '')});
})
2.7,原生提供方法
public class CommModule extends ReactContextBaseJavaModule {
@ReactMethod
public void refleshUserInformation() {
EventBus.getDefault().post("EVENT_REFLESH_USER_DATA");//登录刷新用户头像等信息
}
}
2.8,原生调用RN的方法
发送事件(其中EVENT_NAME与msg都为String类型)
mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(EVENT_NAME, msg);
注册事件
DeviceEventEmitter.addListener('Event',(str)=>{
})
2.9,对于RN多级回退
this.navigateBack(this.params.key)
同时需要在中间页面维护页面标志key值
(key:this.key)
RN与原生交互参考https://blog.csdn.net/asddavid/article/details/53338616
三、RN的flex布局方式:
flex:1 ->设置占据剩余全部布局
flexDiretion:’row’ ->设置水平布局,默认垂直布局
row:主轴为水平方向,起点在左端。
row-reverse:主轴为水平方向,起点在右端。
column(默认值):主轴为垂直方向,起点在上沿。
column-reverse:主轴为垂直方向,起点在下沿。
justify-content: ‘center ’ ->定义了项目在主轴上的对齐方式。
flex-start(默认值):左对齐
flex-end:右对齐
center: 居中
space-between:两端对齐,项目之间的间隔都相等。
space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
alignItems:'center' ->定义项目在交叉轴上如何对齐
配合justify-content:‘center’可以实现gravity:”center”的效果
flex-start:交叉轴的起点对齐。
flex-end:交叉轴的终点对齐。
center:交叉轴的中点对齐。
baseline: 项目的第一行文字的基线对齐。
stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
align-content:‘center’ ->定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用
使用略少
flex-start:与交叉轴的起点对齐。
flex-end:与交叉轴的终点对齐。
center:与交叉轴的中点对齐。
space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
stretch(默认值):轴线占满整个交叉轴。
Flex布局相关参考http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
四、RN控件使用
<Image source={search_img} style={{marginLeft: 8, width: 17, height: 17,marginTop:2}}/>
<Text style={{textColor:color.black_more_light,marginLeft:constant.dp10}}>
{strings.searchCategory}
</Text>
<FavoritesItam
strGoodsImageUri={item.strGoodsImageUri}
strGoodsContent={item.strGoodsContent}
partNum={item.partNum}
clickItemJump={()=>this.clickItemJump(item,index)}
clickItemLike={()=>this.clickItemMore(item,index)}
strShopName={item.strShopName}/>
声明
const FavoritesItem = props => {
const {
strGoodsImageUri,
...attributes
} = props
return (
<View></View>
);
};
export default FavoritesItem;
RN控件相关参考官网https://facebook.github.io/react-native/docs/next/listview.html
五、ES6语法特性
数据与对象的解构:
let { bar, foo } = { foo: "aaa", bar: "bbb" };
函数的扩展:
function foo(x = 5, y = 6) {
console.log(x, y);
}
标签模板:
let a = 5;
let b = 10;
let s=`Hello ${ a + b } world ${ a * b }`
console.log(s)
Es6语法特性参考http://es6.ruanyifeng.com/#docs/string
六、react native屏幕适配
/**
* 屏幕适配工具类
* ui设计基准,iphone 6
* width:750
* height:1334
* 灵活使用以下方法进行适配
* 思想主要是以1,react-native提供的dp、2,flex权重进行适配为主,以3,getAutolayoutWidth()、4,自行计算宽度为辅。一般情况不按高度适配:
*
* 1,布局适配方法
* 1.1,使用react-native提供的dp进行适配
* 1.2,使用权重flex=1进行比例适配
* 1.3,使用提供的getAutolayoutWidth()进行适配
*
* 2,文字适配方法
* 2.1,对于限定行数的Text
* 使用numberOfLines={1}属性,多余部分会以省略号显示。
* 也可以加入属性:ellipsizeMode,取值为:
* head:从文本的开头进行截断,并在文本的开头添加省略号,例如:...xyz。
* middle :从文本的中间进行截断,并在文本的中间添加省略号,例如:ab...yz。
* tail:从文本的末尾进行截断,并在文本的末尾添加省略号,例如:abcd...。
* clip :文本的末尾显示不下的内容会被截断,并且不添加省略号,clip只适用于iOS平台。
* 如要显示具体详情可以咨询产品,加入文字详情弹窗
* 2.2,对于不限行的Text,可以自动排到下一行,页面可以考虑用ScrollView包裹
*
* 3,图片适配方法
* 3.1,对于占据空间比较小的icon,一般不会产生适配问题
* 3.1,1,进行正常的react-native的dp适配即可
* 3.2,对于占据空间比较大的图片,对不同手机的显示效果区别较大
* 3.2,1,使用工具类中提供的screenWidth自行计算百分比宽度
* 3.2.2,使用提供的getAutolayoutWidth()进行适配
*/
import {
Dimensions,
Platform,
PixelRatio
} from 'react-native';
// 设计稿宽度
const designPageScreenWidth=750;
// 设计稿高度
const designPageScreenHeight=1334;
const MAX_SCREENT = Math.max(Dimensions.get('window').width, Dimensions.get('window').height);
const MIN_SCREENT = Math.min(Dimensions.get('window').width, Dimensions.get('window').height);
const __ISIPHONEX__ = Platform.OS === 'ios' && (MIN_SCREENT === 375.0 && MAX_SCREENT === 812.0);
/**
* 设计稿宽度px=>动态实际手机宽度dp
* 有需要以宽度适配为主,注意这里是入参是px
* 实测在react-native中iphone X,iphone 6的宽度dp都是375,android Nexus_5X_API_27的宽度dp为411.42857142857144
*/
function getAutolayoutWidth(width:number){
return width/designPageScreenWidth*Dimensions.get('window').width;
}
/**
* 设计稿高度px=>动态实际手机高度dp
* 高度适配场景较少,慎用
*/
function getAutolayoutHeight(height:number){
return height/designPageScreenHeight*Dimensions.get('window').height;
}
/**
* 对外提供的方法
*/
export default{
screenWidth: Dimensions.get('window').width,
screenHeight: Dimensions.get('window').height,
pixelRatio: PixelRatio.get(),
onePixel: 1 / PixelRatio.get(),
statusBarHeight: Platform.OS === 'ios' ? (__ISIPHONEX__ ? 44 : 20) : 20,// (Platform.OS === 'ios' ? 20 : 0),
headerHeight: Platform.OS === 'ios' ? (__ISIPHONEX__ ? 88 : 64) : 48,
tabBarHeight: Platform.OS === 'ios' ? (__ISIPHONEX__ ? 83 : 49) : 49,
isIOS: Platform.OS === 'ios',
isIOSSmall: Platform.OS === 'ios' && Dimensions.get('window').height === 568,// phoneSE,phone4,phone5,phone5s
isIOSNomarl: Platform.OS === 'ios' && Dimensions.get('window').height === 667,// phone6,phone7,phone8
isIOSP: Platform.OS === 'ios' && Dimensions.get('window').height === 736,//phone6p,phone7p,phone8p
isIOSX: Platform.OS === 'ios' && Dimensions.get('window').height === 812,
getAutolayoutWidth,
getAutolayoutHeight,
}