如何在iOS原生項(xiàng)目中集成react-native項(xiàng)目此處不再贅述设凹。
這里簡(jiǎn)單描述如何在iOS原生項(xiàng)目多個(gè)地方進(jìn)入react-native模塊抡驼。
或許剛開始在iOS原生項(xiàng)目中集成react-native模塊的時(shí)候很開心绰垂,集成也很簡(jiǎn)單噩死,但是藕赞,有一天孤紧,增加需求了当娱,需要在另外一個(gè)地方增加一個(gè)react-native模塊吃既。瞬間懵逼,有木有跨细?如何處理呢鹦倚?
我們知道,index.ios.js
可以看做是iOS模塊的入口冀惭,但是這個(gè)入口似乎只有一個(gè)震叙,從這個(gè)地方入手的話,似乎不太好處理散休,反正我是放棄治療了媒楼。
在網(wǎng)上找了一段時(shí)間,沒有找到合適的方法戚丸。于是划址,我決定自己整個(gè)方案出來(或許網(wǎng)上有吧??)。在此之前限府,我在做H5項(xiàng)目的時(shí)候夺颤,后來將頁面都改成JSP了,里面有個(gè)重定向的知識(shí)點(diǎn)胁勺,由此得到啟發(fā)世澜,就有了下面的一個(gè)方案。然后呢署穗?于一次異想天開宜狐,得出了另一個(gè)方案(注冊(cè)多個(gè)組件)势告。
兩種方案都用到了RCTRootView
,假設(shè)現(xiàn)在需要加載兩個(gè)react-native模塊抚恒,一個(gè)是Discover
咱台,另一個(gè)是Profile
。
下面分別說說這兩個(gè)方案:
方案一俭驮、注冊(cè)多個(gè)組件
這種方式利用"moduleName"
來實(shí)現(xiàn)回溺,具體的玩法是這樣的:
1、在原生項(xiàng)目中的一個(gè)地方混萝,
RCTRootView * rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"Discover" initialProperties:props
launchOptions:nil];
在另一處
RCTRootView * rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"Profile" initialProperties:props
launchOptions:nil];
這樣就有了兩個(gè)react-native的入口了遗遵。組件名也有了。
2逸嘀、在react-native中的index.ios.js
文件中同時(shí)注冊(cè)兩個(gè)組件作為兩個(gè)react-native模塊的入口
AppRegistry.registerComponent('Discover', () => Root1);
AppRegistry.registerComponent('Profile', () => Root2);
采用這種方式的好處是:兩個(gè)react-native模塊的代碼相對(duì)分離车要,一個(gè)進(jìn)入組件Root1
,另一個(gè)進(jìn)入Root2
崭倘。后面的都是熟悉的玩法了翼岁。但是用的node_modules是一套,還是有影響的司光。
方案二琅坡、重定向(重新設(shè)置路由)
這種方式利用"initialProperties"
來實(shí)現(xiàn),我們事先傳入react-native模塊路由名残家,具體的玩法是這樣的:
1榆俺、在原生項(xiàng)目中,
NSDictionary *props = @{ @"routeName" : self.routeName };
RCTRootView * rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"MyApp" initialProperties:props
launchOptions:nil];
我們?cè)谠?xiàng)目中傳入路由名Discover
或Profile
(字符串即可)坞淮。
2茴晋、在react-native項(xiàng)目中,只要在組件將要加載的時(shí)候回窘,修改路由即可晃跺。
a)、如果用的是較早的導(dǎo)航Navigator
組件毫玖,這樣玩
let initialRoute = null;
export default class App extends Component {
componentWillMount() {
if (this.props.routeName === "Discover") {
initialRoute = Discover;
} else if (this.props.routeName === "Profile") {
initialRoute = Profile;
}
}
render() {
return (
<Navigator
initialRoute={{name: 'initialRouteName', component: initialRoute}}
renderScene={
(route, navigator) => {
_navigator = navigator;
let Component = route.component;
return <Component {...route.params} navigator={navigator}/>
}
}
configureScene={(route) => Navigator.SceneConfigs.HorizontalSwipeJump}
/>
);
}
}
這樣以來掀虎,就修改了初始化路由,實(shí)現(xiàn)了從不同入口進(jìn)入react-native模塊付枫。
b)烹玉、如果用的Facebook目前推薦的react-navigation組件,玩法是這樣的:
首先阐滩,先接收到原生項(xiàng)目傳遞過來的默認(rèn)屬性值二打,即routeName,
export default class App extends Component {
render() {
return (
// screenProps 為了傳遞從原生傳遞過來的屬性給項(xiàng)目的initialRoute
<RoutesConfig screenProps={this.props}/>
);
}
}
其次掂榔,創(chuàng)建一個(gè)組件專門處理初始化路由
class Redirect extends React.Component {
// 重定向到相應(yīng)的RN模塊
componentWillMount() {
NavigationUtil.reset(this.props.navigation, this.props.screenProps.routeName);
}
render() {
return (
<View />
);
}
}
這里render
一個(gè)空白頁继效,同樣是在componentWillMount() {}
中更改初始化路由症杏。重新設(shè)置路由的方法在react-navigation中可以查閱。
最后瑞信,將Redirect
組件作為react-navigation組件的初始化路由厉颤。
const RoutesConfig = StackNavigator(
{
Redirect: {
screen: Redirect,
},
Discover: {screen: Discover},
Profile: {screen: Profile},
},
{
initialRouteName: 'Redirect', // 默認(rèn)顯示界面
mode: 'card',
headerMode: 'screen',
cardStyle: {
paddingTop: Platform.OS === 'ios' ? 0 : StatusBar.currentHeight
},
navigationOptions: ({navigation}) => ({
headerStyle: {
backgroundColor: '#48B4EB'
},
headerTitleStyle: {
color: '#fff',
fontSize: 18
},
headerTintColor: '#fff',
}),
}
);
這種方式在一個(gè)空白頁處理,雖說是在組件加載之前更改了初始化路由逼友,總歸不好。
到此差不多結(jié)束了帜乞。然而筐眷,感覺這兩種方式都不是很優(yōu)秀的解決方案黎烈,有更好的方式歡迎補(bǔ)充,在此拜謝匀谣!