React Native出現的目的本就是「learn once, write anywhere」,Facebook但願人們可以學習一次,處處使用,可是一樣是JS代碼,從前端移植到RN,或者RN移植到前端,卻並無想象的那麼容易。事實上除了語法相同外,還有不少不同的地方,致使咱們無法作到直接copy,如下是我在作遷移代碼的時候,總結的一些經驗css
Antd Mobile的螞蟻金服開源的一套UI組件,已經實現了前端、iOS、Android的三端統一UI,推薦你們多多使用前端
多用direction justify align 屬性,由於某些移動端瀏覽器不支持Flex功能,影響到適配,而antd已經幫我作過了,只是須要咱們採用如下寫法,不然無效 例如:react
Good:git
<Flex direction="column" align="start" justify="startt">
複製代碼
Bad:(這種寫法並無利用到Flex自己的適配)web
<Flex style={{
flexDirection: "column",
backgroundColor: "white",
justifyContent: "flex-start"
}}>
複製代碼
這樣的話,由於前端的兼容性你須要寫不少適配的css代碼,例如npm
{
display: flex;
display: -webkit-flex;
flex-direction: row;
-webkit-flex-direction: row;
justify-content: flex-start;
-webkit-justify-content: flex-start;
align-items: center;
-webkit-align-items: center;
}
複製代碼
由於某些狀況下Flex沒法使用,例如RN端的Touchable組件只能包裹原生組件,必須用View替代Flex,而View和Flex的默認方向是不同的,所以顯示寫出flexDirection,明確告知方向,方便遷移者改動代碼react-native
Good:瀏覽器
<Flex direction="column">
{...}
</Flex>
複製代碼
Bad:(替換成View時候方向會錯)bash
<Flex>
{...}
</Flex>
複製代碼
在RN 0.51版本下,antd的ListView會報錯,仍是使用RN提供的ListView,只須要修改import ListView便可,其餘寫法徹底一致antd
// 不推薦
import { ListView } from "antd-mobile";
// 推薦
import { ListView } from "react-native";
複製代碼
某些頁面很複雜,常見的一種寫法是將頁面拆分紅若干模塊,每一個模塊寫一個moduleRender函數,再在render函數裏分別調用,相似如下
Bad:
class SomeComponent extends Component {
renderSubOne() {
return <Flex>{...}</Flex>;
}
renderSubTwo() {
return <Flex>{...}</Flex>;
}
renderSubThree() {
return <Flex>{...}</Flex>;
}
render() {
return <Flex>
{this.renderSubOne()}
{this.renderSubTwo()}
{this.renderSubThree()}
</Flex>
}
}
複製代碼
Good:
class SomeComponent extends Component {
render() {
return <Flex>
<SubOne />
<SubTwo />
<SubThree />
</Flex>
}
}
複製代碼
關於樣式的寫法,RN和前端有個顯著的差異 RN:
import { StyleSheet } from "react-native";
const styles = StyleSheet.create({
someContainer: {
fontSize:16,
fontWeight: 'bold',
},
...
})
<Flex style={styles.container} />
複製代碼
前端:
// js 文件
import CSSModules from 'react-css-modules';
...
@CSSModules(styles)
...
<Flex className="someContainer">
複製代碼
// css文件
.someContainer{
font-size: 16px;
font-weight: bold;
}
複製代碼
由上面示例可知
而這些不一樣都須要咱們遷移的時候一一手動修改,工做量很大
推薦的寫法,是統一使用RN的寫法:
// 前端js文件
const styles = { // 這裏不須要像RN同樣,使用StyleSheet.create
someContainer: {
fontSize:16,
fontWeight: 'bold',
},
...
}
<div style={styles.container} />
複製代碼
挑選第三方組件要注意
有一些差別是前端和RN自然的差別,須要注意
加載圖片資源在兩端寫法並不同,須要手動修改
前端:
<img style={{ width: 98, height: 82 }} src={nullImg} alt="nullImg" />
複製代碼
RN:
<Image style={{ height: 15, width: 15, marginLeft: 10 }} source={{ uri: 'search3' }} />
複製代碼
須要特別注意一下的是,React Native 0.50.3
之後,Image組件再也不能包裹child
<Image> // 0.50.3之後,這種寫法報錯
{...child...}
</Image>
複製代碼
若是確實須要,只能用絕對位置了
前端渲染文本有多種標籤,div
,span
等,可是RN端只有一種Text
,這在遷移時會帶來很大的工做量,文本散落在各個地方,須要人工一一替換。 推薦使用react-intl
,RN端是react-intl-native
這個有Yahoo提供的第三方組件,實現了在前端、RN端的統一
Bad:
<div>文本</div>
<span>文本</span>
複製代碼
Good:
<FormattedMessage
style={styles.valueDesc}
id="someId"
defaultMessage={text}
/>
複製代碼
前端:
// 能夠添加在任何標籤上
<div onclick={()=>{}} />
<img onclick={()=>{}} />
複製代碼
RN:
<TouchableHighlight onPress={}>// 只能有一個子元素,且必須是RN原生組件,不能是自定義組件
<View> // 要用一個View來包裹更多的元素
{child}
</View
</TouchableHighlight>
複製代碼
由上可知,點擊事件遷移時,經常須要改動較多的代碼
react-route
react-navigation
,react-native-navigation
等寫法上會有不一樣,須要遷移者根據具體選擇的庫,手動修改
PropTypes是React提供的一種類型檢測工具,可是隨着版本的變遷,從React 15.5
起,PropTypes被移出了React,造成了一個單獨的庫,若是前端和RN兩邊版本不一致,還有可能須要人工大量修改
// react version < 15.5
import React, { Component, PropTypes } from 'react';
// react version >= 15.5
import React, { Component } from 'react';
import PropTypes from 'prop-types';
複製代碼
前端js代碼的運行環境一般是瀏覽器,瀏覽器自己提供全局變量window,而RN端則沒有,所以不要在前端使用window全局變量,而是要使用導入文件
Bad:
window.someVar = var
複製代碼
Good:
// 新建constants.js文件
const object = {
website:'http://www.hao123.com',
name:'好123',
};
export default object;
// 須要使用時導入
import constants from './constansts.js'
<Text>{constants.name}</Text>
複製代碼