Skip to content

Commit

Permalink
rn 启动支持动态传入参数,跳转指定页面,增加透传react-navigation参数 (NervJS#9454)
Browse files Browse the repository at this point in the history
* feat: rn 启动支持动态传入参数,跳转指定页面

* fix(router-rn): 透传react-navigation参数

* fix(rn-runner): platform default to android

Co-authored-by: yechunxi <[email protected]>
  • Loading branch information
zhiqingchen and yechunxi authored Jun 4, 2021
1 parent 065b58b commit b73d526
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 30 deletions.
2 changes: 1 addition & 1 deletion packages/taro-cli/src/presets/platforms/rn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default (ctx: IPluginContext) => {
useConfigName: 'rn',
async fn ({ config }) {
const { appPath, nodeModulesPath } = ctx.paths
const { deviceType, port, resetCache } = ctx.runOpts.options
const { deviceType = 'android', port, resetCache } = ctx.runOpts.options
const { npm } = ctx.helper
printDevelopmentTip('rn')

Expand Down
14 changes: 1 addition & 13 deletions packages/taro-router-rn/src/rootNavigation.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// RootNavigation.js
import * as React from 'react'
import { camelCase } from 'lodash'
import { parseUrl } from 'query-string'
import { StackActions, NavigationContainerRef } from '@react-navigation/native'
import { getTabBarPages, setTabInitRoute } from './utils/index'
import { getTabBarPages, setTabInitRoute, handleUrl } from './utils/index'
import { CallbackResult, BaseOption } from './utils/types'
// import { getOpenerEventChannel } from './getOpenerEventChannel'

Expand Down Expand Up @@ -48,17 +47,6 @@ export function reLaunch (option: NavigateOption): Promise<CallbackResult> {
return navigate(option, 'reLaunch')
}

// 处理url转换成pageName与params
export function handleUrl (url: string): Record<string, unknown> {
const path = url.split('?')[0]
const pageName = camelCase(path.startsWith('/') ? path : `/${path}`)
const params = parseUrl(url.startsWith('/') ? url.substr(1) : url).query || {}
return {
pageName,
params
}
}

export function navigate (option: NavigateOption | NavigateBackOption, method: NavigateMethod): Promise<CallbackResult> {
const { success, complete, fail } = option
let errMsg
Expand Down
88 changes: 73 additions & 15 deletions packages/taro-router-rn/src/router.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
/* eslint-disable react/no-children-prop */
import * as React from 'react'
import { StyleProp, ViewStyle } from 'react-native'
import { camelCase } from 'lodash'
import { NavigationContainer } from '@react-navigation/native'
import { BackBehavior } from '@react-navigation/routers/src/TabRouter'
import { createStackNavigator, CardStyleInterpolators } from '@react-navigation/stack'
import { StackHeaderOptions } from '@react-navigation/stack/src/types'
import { StackHeaderOptions, StackCardMode, StackHeaderMode } from '@react-navigation/stack/src/types'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import { navigationRef } from './rootNavigation'
import CustomTabBar from './view/TabBar'
import HeadTitle from './view/HeadTitle'
import BackButton from './view/BackButton'
import { getTabItemConfig, getTabVisible, setTabConfig, getTabInitRoute } from './utils/index'
import { getTabItemConfig, getTabVisible, setTabConfig, getTabInitRoute, handleUrl } from './utils/index'

interface WindowConfig {
pageOrientation?: 'auto' | 'portrait' | 'landscape'
Expand Down Expand Up @@ -52,15 +54,29 @@ interface RNConfig {
linking?: string[],
screenOptions?: Record<string, any>,
tabBarOptions?: Record<string, any>,
options?: Record<string, any>
options?: Record<string, any>,
tabProps?:{
backBehavior?: BackBehavior;
lazy?: boolean,
detachInactiveScreens?:boolean,
sceneContainerStyle?: StyleProp<ViewStyle>
},
stackProps?:{
keyboardHandlingEnabled?:boolean,
mode?: StackCardMode;
headerMode?: StackHeaderMode;
detachInactiveScreens?:boolean,
}
}

export interface RouterConfig {
pages: PageItem[],
tabBar?: ITabBar,
window?: WindowConfig,
linkPrefix?: string[],
rnConfig?: RNConfig
rnConfig?: RNConfig,
initParams?:Record<string, any>, // 原生启动传递的参数
initPath?: string, // 原生启动时传入的参数路径
}

export function createRouter (config: RouterConfig): React.ReactNode {
Expand Down Expand Up @@ -157,29 +173,55 @@ function getTabItem (config: RouterConfig, tabName: string) {

function getInitRouteName (config: RouterConfig) {
let initRoute = ''
const initPath = config.initPath || ''
const rn = config.rnConfig || {}
if (rn?.initialRouteName) {
if (initPath) {
initRoute = handleUrl(initPath).pageName
} else if (rn?.initialRouteName) {
initRoute = camelCase(rn.initialRouteName)
} else {
initRoute = config.pages[0].name
}
return initRoute
}

function getInitTabRoute (config:RouterConfig) {
function getInitTabRoute (config: RouterConfig) {
const pageList = config.pages
const tabNames = getTabNames(config)
const initPath = config.initPath || ''
let initTabName = ''
for (let i = 0; i < pageList.length; i++) {
const item = pageList[i]
if (tabNames.indexOf(item.name) !== -1) {
initTabName = item.name
break
if (initPath) { // 优先原生传入的路由
const route = handleUrl(initPath).pageName
for (let i = 0; i < tabNames.length; i++) {
if (route === tabNames[i]) {
initTabName = tabNames[i]
break
}
}
}
if (!initTabName) {
for (let i = 0; i < pageList.length; i++) {
const item = pageList[i]
if (tabNames.indexOf(item.name) !== -1) {
initTabName = item.name
break
}
}
}
return initTabName
}

function getInitParams (config, pageName) {
let params: any = {}
const initRouteName = getInitRouteName(config)
if (initRouteName === pageName) {
const initPath = config.initPath || ''
params = handleUrl(initPath).params
params = Object.assign({}, params, config.initParams)
}
return params
}

function createTabStack (config: RouterConfig, parentProps: any) {
const Tab = createBottomTabNavigator()
const tabBar = config.tabBar
Expand All @@ -193,11 +235,13 @@ function createTabStack (config: RouterConfig, parentProps: any) {
const path = item.pagePath.startsWith('/') ? item.pagePath : `/${item.pagePath}`
const tabName = camelCase(path)
const tabPage: PageItem = getTabItem(config, tabName) as PageItem
const initParams = getInitParams(config, tabName)
const tabNode = React.createElement(Tab.Screen, {
key: `tab${tabName}`,
name: `${tabPage.name}`,
options: tabItemOptions,
component: tabPage.component,
initialParams: initParams,
...parentProps
})
tabList.push(tabNode)
Expand All @@ -218,9 +262,12 @@ function createTabStack (config: RouterConfig, parentProps: any) {
}, userTabBarOptions)

const tabNames = getTabNames(config)
const tabProps = config.rnConfig?.tabProps || {}

const tabInitRouteName = getTabInitRoute() || getInitTabRoute(config) || tabNames[0]
return React.createElement(Tab.Navigator,
{
...tabProps,
tabBarOptions: tabBarOptions,
tabBar: (props) => createTabBar(props, userOptions),
initialRouteName: tabInitRouteName,
Expand Down Expand Up @@ -272,7 +319,6 @@ function getLinkingConfig (config: RouterConfig) {
function createTabNavigate (config: RouterConfig) {
const screeList: any = []
const Stack = createStackNavigator()

// 第一个页面是tabbar的
const tabScreen = React.createElement(Stack.Screen, {
name: 'tabNav',
Expand All @@ -282,17 +328,21 @@ function createTabNavigate (config: RouterConfig) {
screeList.push(tabScreen)
const pageList = getPageList(config)
pageList.forEach(item => {
const initParams = getInitParams(config, item.name)
const screenNode = React.createElement(Stack.Screen,
{
key: `${item.name}`,
name: `${item.name}`,
component: item.component
component: item.component,
initialParams: initParams
}, null)
screeList.push(screenNode)
})
const linking = getLinkingConfig(config)
const stackProps = config.rnConfig?.stackProps
const tabStack = React.createElement(Stack.Navigator,
{
...stackProps,
screenOptions: () => {
const options = getCurrentOptions()
const defaultOptions = getStackOptions(config)
Expand All @@ -310,17 +360,25 @@ function createStackNavigate (config: RouterConfig) {
if (pageList.length <= 0) return null
const screenChild: any = []
pageList.forEach(item => {
const initParams = getInitParams(config, item.name)
const screenNode = React.createElement(Stack.Screen,
{
key: `${item.name}`,
name: `${item.name}`,
component: item.component
component: item.component,
initialParams: initParams
}, null)
screenChild.push(screenNode)
})
const linking = getLinkingConfig(config)
const stackProps = config.rnConfig?.stackProps
const stackNav = React.createElement(Stack.Navigator,
{ screenOptions: getStackOptions(config), children: screenChild }, screenChild)
{
...stackProps,
screenOptions: getStackOptions(config),
children: screenChild,
initialRouteName: getInitRouteName(config)
}, screenChild)
return React.createElement(NavigationContainer, { ref: navigationRef, linking: linking, children: stackNav }, stackNav)
}

Expand Down
12 changes: 12 additions & 0 deletions packages/taro-router-rn/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { camelCase } from 'lodash'
import { parseUrl } from 'query-string'
import { TaroTabBarConfig, CallbackResult, OptionsFunc } from './types'

const globalAny: any = global
Expand Down Expand Up @@ -109,3 +110,14 @@ export function getTabBarPages (): string[] {
})
return pages
}

// 处理url转换成pageName与params
export function handleUrl (url: string): Record<string, any> {
const path = url.split('?')[0]
const pageName = camelCase(path.startsWith('/') ? path : `/${path}`)
const params = parseUrl(url.startsWith('/') ? url.substr(1) : url).query || {}
return {
pageName,
params
}
}
5 changes: 4 additions & 1 deletion packages/taro-runtime-rn/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ export function createReactNativeApp (component: React.ComponentClass, config: R
const isReactComponent = isClassComponent(component)

const NewAppComponent = (AppCompoent) => {
return class Entry extends React.Component {
return class Entry extends React.Component <any, any> {
render () {
let props: React.Props<any> | null = null

if (isReactComponent) {
props = { ref }
}
const { initPath = '', initParams = {} } = this.props
routerConfig.initPath = initPath
routerConfig.initParams = initParams
return React.createElement(TCNProvider, { ...this.props },
React.createElement(AppCompoent, {
...props,
Expand Down

0 comments on commit b73d526

Please sign in to comment.