-
调整目录结构,根目录增加
index.js
和index.ios.js
。// index.js import App from "./Main"; import { Package } from "miot"; Package.entry(App); // index.ios.js import "./index.js";
-
原有的
Main/index.ios.js
更名为Main/index.js
,删掉其中注册app入口的一行:AppRegistry.registerComponent()
。 -
安装插件使用的第三方库(框架
package.json
中未包含)。比如闹钟使用到的react-native-swipeout
。 -
引用依赖尽量使用es6的
import
,而不是require
。 -
RN54废弃了
react-native
中的Component
,所有组件将继承react
的Component
。// old var React = require('react-native'); var { StyleSheet, Text, DeviceEventEmitter, PixelRatio, } = React; // new import React from 'react'; import { StyleSheet, Text, DeviceEventEmitter, PixelRatio, } from 'react-native';
-
RN54将
PropTypes
从react-native
中抽离出来,独立成prop-types
。// old var propTypes = { source: React.PropTypes.object, highlightedSource: React.PropTypes.object, onPress: React.PropTypes.func, }; // new import PropTypes from 'prop-types'; // ... var propTypes = { source: PropTypes.object, highlightedSource: PropTypes.object, onPress: PropTypes.func, };
-
React.createClass
报错解决方案// old var ImageButton = React.createClass({ propTypes: propTypes, getInitialState: function() { }, getDefaultProps: function() { }, //... render: function() { }, }) // new // RN54不再支持使用createClass创建组件, 改为继承至React.Component // key-value形式改为声明语句 export default class ImageButton extends React.Component { static propTypes = propTypes; static initialState = { }; static defaultProps = { }; //... render() { } }
-
切换路由框架(❗️)
-
所有页面删除之前的路由相关代码:
// old class MyComponent extends React.Component { // ... } // ... var route = { title: xxx, component: MyComponent, navBarStyle: { backgroundColor: '#f2f2f2', }, }; module.exports = { component: MyComponent, route: route, } // new export default class MyComponent extends React.Component { // ... } // ... // 摈弃之前的路由系统写法 // var route = { // title: xxx, // component: MyComponent, // navBarStyle: { // backgroundColor: '#f2f2f2', // }, //}; // module.exports = { // component: MyComponent, // route: route, // }
-
在入口文件
Main/index.js
中集中管理所有的页面,增加以下代码:// 导航相关组件 import { createStackNavigator } from 'react-navigation'; import { TitleBarBlack } from 'miot/ui'; // 导入所有的页面 import SceneMain from './SceneMain'; import MainPage from './MainPage'; import MHSetting from './MHSetting'; // ... const RootStack = createStackNavigator( { // ... SceneMain: SceneMain, MainPage: MainPage, MHSetting: MHSetting, // ... }, { initialRouteName: 'MainPage', navigationOptions: ({ navigation }) => { return { header: <TitleBarBlack title={navigation.state.params ? navigation.state.params.title : ''} style={{ backgroundColor: '#fff' }} onPressLeft={() => { navigation.goBack(); }} />, }; }, } );
-
页面跳转,包括参数传递和参数获取
// old this.props.navigator.push({ // 跳转页面 route, // 传参,在跳转页面中可通过props直接访问,即:this.props.key passProps: { key: value }, }); // new this.props.navigation.navigate('ComponentName', { key: value }); // 在跳转页面获取参数 // method 1 this.props.navigation.state.params.key // method 2 this.props.navigation.getParam("key");
-
返回上级页面
-
// old this.props.navigator.pop(); // new this.props.navigation.goBack();
-
退出插件
-
// old MHPluginSDK.closeCurrentPage(); // new import { Package } from "miot"; Package.exit()
-
页面自定义导航栏
// 所有页面默认沿用index.js中RootStack定义的导航栏样式 const RootStack = createStackNavigator( ... navigationOptions: ({ navigation }) => { return { header: <TitleBarBlack title={navigation.state.params ? navigation.state.params.title : ''} style={{ backgroundColor: '#fff' }} onPressLeft={() => { navigation.goBack() }} />, }; }, ... ); // 自定义导航栏样式 export default class AddReminder extends React.Component { // 表示不使用默认的导航栏 static navigationOptions = ({ navigation }) => { return { header: null }; }; //... render() { return ( // 自定义标题的样式和颜色,左右按钮的样式、颜色以及绑定事件 <TitleBarBlack title="newTitle" style={{ backgroundColor: 'red' }} onPressLeft={() => { this.props.navigation.goBack() }} rightText="save" leftText="cancel" onPressRight={() => { this._save(); }} /> //... ) }
-
监听导航栏的生命周期
// old // 可监听'willfocus'和'didfocus' this._didFocusListener = DeviceEventEmitter.addListener('didfocus', ({route}) => { console.log(route); } // new // 可监听'willBlur', 'willFocus', 'didFocus', 'didBlur' this._didFocusListener = this.props.navigation.addListener('didFocus', payload => { console.log(payload); }
-
导航栏更新机制
// Eg. change device name static navigationOptions = ({ navigation }) => { return { header: <TitleBarBlack title={navigation.state["params"] ? navigation.state.params.name : Device.name} style={{ backgroundColor: '#fff' }} onPressLeft={() => { Package.exit() }} onPressRight={() => { navigation.navigate('MHSetting', { 'title': '设置' }); }} /> }; }; // 设置中改名之后,首页title同步改名 this._deviceNameChangedListener = DeviceEvent.deviceNameChanged.addListener((device) => { this.props.navigation.setParams({ name: device.name }); this.forceUpdate(); });
-
-
组件相关
-
新框架调整了
ImageButton
,适用于两个平台。// old var ImageButton = require('../CommonModules/ImageButton'); // new import ImageButton from 'miot/ui/ImageButton';
-
Image
不再允许嵌套// old <Image> <Text></Text> </Image> // old,✅ <Animated.Image> <Animated.Text></Animated.Text> </Animated.Image> // new <ImageBackground> <Text></Text> </ImageBackground> // not allowed,❌ <Animated.ImageBackground> <Animated.Text></Animated.Text> </Animated.ImageBackground> // alternative solution,👌 <Animated.Image/> <Animated.View style={{position:'absolute'}}> <Animated.Text></Animated.Text> </Animated.View>
-
SwitchIOS
废弃,Switch
跨平台解决方案// old <SwitchIOS> </SwitchIOS> // new // cross-platform solution import { RkSwitch } from 'react-native-ui-kitten'; <RkSwitch> </RkSwitch>
-
DatePicker
跨平台解决方案// old import {DatePickerIOS} from 'react-native' <DatePickerIOS style={styles.datePicker} date={this.state.time} mode="time" onDateChange={(d) => this.setState({ time: d })} /> // new // cross-platform,推荐使用第三方库rmc-date-picker // 常用属性和之前几乎一致,UI也能满足要求 import DatePicker from "rmc-date-picker";goBack <DatePicker style={styles.datePicker} defaultDate={this.state.time} mode="time" onDateChange={(d) => this.setState({ time: d })} use12Hours={true} locale={LocalizedStrings} />
-
Picker
跨平台解决方案// old import {Picker} from 'react-native' <Picker selectedValue={this.state.pickerValue} style={styles.picker} onValueChange={(v) => this._setPickerValue(v)}> <Picker.Item label={"1"} value={1} /> <Picker.Item label={"2"} value={2} /> <Picker.Item label={"3"} value={3} /> </Picker> // new // cross-platform,推荐使用第三方库rmc-picker // Picker属性一致,Picker.Item换成Text即可 import Picker from "rmc-picker"; <Picker selectedValue={this.state.pickerValue} style={styles.picker} onValueChange={(v) => this._setPickerValue(v)}> <Text label={"1"} value={1}>1</Text> <Text label={"2"} value={2}>2</Text> <Text label={"3"} value={3}>3</Text> </Picker>
-
提示的跨平台解决方案
// old MHPluginSDK.showLoadingTips("loading"); MHPluginSDK.dismissTips(); MHPluginSDK.showFailTips("fail"); MHPluginSDK.showFinishTips("finish"); AlertIOS.alert(); // new import { LoadingDialog, MessageDialog } from "miot/ui/MessageDialog"; <LoadingDialog title='title' message='message' onDismiss={() => {}} visible={this.state.visible} /> <MessageDialog title='title' message='message' cancel='cancel' confirm='ok' onCancel={() => {}} onConfirm={() => {}} onDismiss={() => {}} visible={this.state.visible} />
- 图片以及其他资源的引用方式
// old
<Image
source={{ uri: MHPluginSDK.basePath + imagePath + imageName }}
style={{ width: x, height: y }}
/>
<Image
style={styles.icon}
source={this.props.app.sourceOfImage(imageName)}
/>
// new
// 不再提供basePth
// static image
<Image
source={require(relativeImagePath + imageName)}
style={{ width: x, height: y }}
/>
// dynamic image at local cache for plugin
<Image
source={{local: imageName}} //local file name
style={{ width: x, height: y }}
/>
<Image
source={{uri: urlToGetImage}} //remote url for image
style={{ width: x, height: y }}
/>
-
其他
TouchableWithoutFeedback
包含的视图在Android
中无法响应滚动手势Text
设置属性numberOfLines
显示多行文字,在Andorid
平台可能会出无法完全显示的问题,可以考虑加上字体或者切换字体。- 旧框架的页面以屏幕左上角为起点定位,所以需要设置
marginTop
为64,新框架以导航栏底部为起点定位,不再需要marginTop
。