,
route: ConfigRoute,
prevRes?: any
): React.ComponentType | undefined;
// 当向router中注册routes时,router初次遍历routes中没有route时被调用
onWalkRoute?(route: ConfigRoute, routeIndex: number, routes: ConfigRouteArray, prevRes?: any): void;
onGetRouteComponentGuards?(
interceptors: RouteGuardInterceptor[],
route: ConfigRoute,
component: any,
componentKey: string,
guardName: string,
options: {
router: ReactViewRouter,
onBindInstance?: OnBindInstance,
onGetLazyResolve?: OnGetLazyResolve,
toResolve: RouteComponentToResolveFn,
getGuard: (obj: any, guardName: string) => any,
replaceInterceptors: (newInterceptors: any[], interceptors: RouteGuardInterceptor[], index: number) => any[]
},
prevRes?: any
): void|boolean;
// 当路由调整被终止时被调用
onRouteAbort?(to: Route, reason?: any, prevRes?: any): void;
onViewContainer?(container: ReactViewContainer|undefined, options: {
routes: MatchedRoute[],
route: MatchedRoute,
depth: number,
router: ReactViewRouter,
view: RouterViewComponent,
}, prevRes?: ReactViewContainer): ReactViewContainer|void;
}
```
#### `install` `ReactVueLike`插件装载方法. 参见: [ReactVueLike](https://github.com/gxlmyacc/react-vue-like)
```js
import vuelike from '@/vuelike';
import ReactViewRouter from 'react-view-router';
const router = new ReactViewRouter();
vuelike.use(router);
```
### 导出的其他方法
- `withRouteGuards` 路由组件的守卫方法:
```js
/**
* 路由组件的守卫注册方法
* @param {Object} component - 路由组件
* @param {Object} guards - 守卫方法
* @param {Class} [componentClass] - 路由组件的类,如果component是被高阶组件包装过的话,可以通过该参数来指明正确的路由组件
* @return {RouteComponentGuards} - 可以被当做`React.forwardRef`来使用的路由组件
**/
function withRouteGuards(component, guards = {}, componentClass?) {}
```
示例:
```js
import React from 'react';
import { RouterView, withRouteGuards } from 'react-view-router';
function HomeIndex() {
return (
HomeIndex
);
}
export default withRouteGuards(HomeIndex, {
beforeRouteEnter(to, from, next) {
console.log('HomeIndex beforeRouteEnter', to, from);
next();
},
beforeRouteLeave(to, from, next) {
// confirm leave prompt
console.log('HomeIndex beforeRouteLeave', this, to, from);
next();
},
beforeRouteUpdate(to, from) {
console.log('HomeIndex beforeRouteUpdate', to, from);
},
beforeRouteResolve(to, from) {
console.log('HomeIndex beforeRouteResolve', to, from);
},
afterRouteLeave(to, from) {
console.log('HomeIndex afterRouteLeave', to, from);
},
});
```
- `lazyImport` 路由组件懒加载方法:
```ts
type LazyImportMethod = (route: ConfigRoute, key: string, router: ReactViewRouter, options: Partial) => P | Promise;
/**
* 路由组件懒加载方法
* @param {LazyImportMethod} importMethod - webpack的import懒加载方法, 示例: () => import('@/components/some-component')
* @return {RouteLazy} - 返回值可以作为路由配置中的component/components值,来实现懒加载
**/
function lazyImport(importMethod: LazyImportMethod, options?: Partial): RouteLazy;
```
- `normalizeRoutes` 正规化路由配置:
```ts
/**
* 正规化路由配置
* @param {UserConfigRoute[]} routes - 为正规化的路由配置
* @param {ConfigRoute} [parent] - 如果提供,则routes将会被当做它的子路由配置信息
* @return {ConfigRouteArray} - 正规化后的路由配置
**/
function normalizeRoutes(routes: UserConfigRoute[], parent?: ConfigRoute): ConfigRouteArray;
```
- `normalizeLocation` 正规化路由字符串或对象为统一格式的路由对象:
```javascript
/**
* 正规化路由字符串或对象为统一格式的路由对象
* @param {Object|string} to - 待正规化的地址对象
* @param {Object} [options] - 其他选项
* @param {Object} [options.route] 地址对象的父路由,如果提供的话,路由中的相对路径将会基于它来解析
* @return {Object} - 正规化后的路由对象: { path: string, pathname: string, search: string, query: Object, ...custom props }
**/
function normalizeLocation(to, options: { route? } = {}) {}
```
- `isLocation`判断 `v`是否是一个路由对象
```javascript
/**
* 判断 `v`是否是一个路由对象
* @param {Object} v - 待判定的对象
* @return {boolean}
**/
function isLocation(v) {}
```
- `matchPath` 只是重新导出,参见: [matchPath](https://reacttraining.com/react-router/web/api/matchPath)
- `createRouterLink` - 创建一个基于某个`router`的`router-link`组件。你可以在创建`router`的同时,创建一个该组件:
```js
import ReactViewRouter, { createRouterLink } from 'react-view-router';
const router = new ReactViewRouter();
const RouterLink = createRouterLink(router);
export {
RouterLink
}
export default router;
```
- `createRouteGuardsRef` 创建路由守卫引用
该方法是在使用者不想使用`useRouteGuardsRef`,而是直接使用`useImperativeHandle`时,通过该方法创建一个和`useRouteGuardsRef`等效的兼容实例。
示例:
```js
import React, { useImperativeHandle } from 'react';
import { createRouteGuardsRef } from 'react-view-router';
import modals from '~/utils/modals';
const Test = React.forwardRef((props, ref) => {
const inputRef = useRef();
useRouteGuardsRef(
ref,
() => createRouteGuardsRef({
async beforeRouteLeave(to, from, next) {
console.log('Test beforeRouteLeave', to, from);
try {
await modals.confirm({ content: '确定要离开吗?' });
next();
} catch (ex) {
next(false);
}
},
beforeRouteUpdate(to, from) {
console.log('Test beforeRouteUpdate', to, from);
},
focus: () => {
inputRef.current.focus();
},
})
);
return (
return ;
);
});
export default Test;
```
- `readRouteMeta` 读取ConfigRoute中`meta`的某个值,当值为函数时,会将其当做
```ts
function (route: ConfigRoute, routes: ConfigRoute[], props: Partial): any
```
回调进行调用,并将其返回值返回;
```javascript
/**
* @param {ConfigRoute} route - 要读取meta的ConfigRoute
* @param {string} key - 要读取meta的参数名
* @param {props: Partial} props - 将作为第三个参数传递给meta的value函数
* @return {any}
**/
function readRouteMeta(route: ConfigRoute, key: string = '', props: {
router?: ReactViewRouter|null,
[key: string]: any
} = {}): any
```
## HOCS/HOOKS
`react-view-router`也支持HOC/HOOKS
### HOCS
### withRouter
获取router实例,函数签名如下:
```javascript
/**
* @param {React.ComponentType} Comp - 待封装的组件
* @param {object} [options] - 选项
* @param {boolean} [options.withRoute] - 是否也获取当前route对象
* @return {React.ComponentType}
**/
const withRouter = (Comp: React.ComponentType, { withRoute: boolean = false }) => React.ComponentType
```
### withRoute
获取route对象,函数签名如下:
```javascript
/**
* @param {React.ComponentType} Comp - 待封装的组件
* @param {object} [options] - 选项
* @param {boolean} [options.withRouter] - 是否也获取当前router实例
* @return {React.ComponentType}
**/
const withRoute = (Comp: React.ComponentType, { withRouter: boolean = false }) => React.ComponentType
```
### withMatchedRoute
获取当前层级匹配的matchedRoute对象,函数签名如下:
```javascript
/**
* @param {React.ComponentType} Comp - 待封装的组件
* @param {object} [options] - 选项
* @param {boolean} [options.withMatchedRouteIndex] - 是否也获取当前层级索引
* @return {React.ComponentType}
**/
const withMatchedRoute = (Comp: React.ComponentType, { withMatchedRouteIndex: boolean = false }) => React.ComponentType
```
### withMatchedRouteIndex
获取当前层级获取当前层级索引,函数签名如下:
```javascript
/**
* @param {React.ComponentType} Comp - 待封装的组件
* @param {object} [options] - 选项
* @param {boolean} [options.withMatchedRoute] - 是否也获取当前层级匹配的matchedRoute对象
* @return {React.ComponentType}
**/
const withMatchedRouteIndex = (Comp: React.ComponentType, { withMatchedRoute: boolean = false }) => React.ComponentType
```
### withRouterView
获取当前层级的RouteView实例,函数签名如下:
```javascript
/**
* @param {React.ComponentType} Comp - 待封装的组件
* @param {object} [options] - 选项
* @return {React.ComponentType}
**/
const withRouterView = (Comp: React.ComponentType, {}) => React.ComponentType
```
### HOOKS
### useRouter
获取router实例,函数签名如下:
```javascript
/**
* @return {ReactViewRouter|null}
**/
const useRouter = (defaultRouter?: ReactViewRouter|null) => ReactViewRouter|null
```
### useRoute
获取route对象,函数签名如下:
```javascript
/**
* @param {ReactViewRouter} [defaultRouter] 默认的路由管理组件,当不传时它会根据上下文来寻找
* @param {object} [options] 匹配选项
* @param {boolean} [options.watch] 是否监听路由变化
* @param {number|boolean = false} [options.delay] 路由发生变化时是否异步通知路由变更
* @param {boolean = true} [options.ignoreSamePath] 路由发生变化前后的路由fullPath相同,则不触发组件重新渲染
* @return {Route}
**/
const useRoute = (
defaultRouter?: ReactViewRouter|null,
options?: {
watch?: boolean,
delay?: boolean|number,
ignoreSamePath?: boolean
}
) => Route
```
### useRouteMeta
获取当前路由层级的路由元信息,你可以读取其中信息,并对它进行修改。
```javascript
/**
* @return {Route}
**/
const useRouteMeta = (key: string|string[]): [Partial, (key: string|string[], value: any) => void]
```
示例:
```js
import { useRouteMeta } from 'react-view-router';
function Test() {
const [title, setTitle] = useRouteMeta('title');
return <>
{title}
>
}
```
### useRouteMetaChanged
注册一个路由元信息变更事件,该方法在通过路由元信息生成数据的组件中会比较有用
```javascript
/**
* @return {Route}
**/
const useRouteMetaChanged = (router: ReactViewRouter, onChange: onRouteMetaChangeEvent, depMetaKeys: string[] = [])
```
示例:
```js
import React, { useState } from 'react';
import { useRouter, useMatchedRoute, useRouteMetaChanged } from 'react-view-router';
function Test() {
const router = useRouter();
const matchedRoute = useMatchedRoute();
const [title, setTitle] = useRouteMeta('title');
useRouteMetaChanged(router, (newVal, oldVal, route) => {
console.log('title changed');
}, ['title']);
return <>
{title}
>
}
```
### useMatchedRoute
获取当前层级匹配的matchedRoute对象,函数签名如下:
```javascript
/**
* @param {ReactViewRouter} [defaultRouter] 默认的路由管理组件,当不传时它会根据上下文来寻找
* @param {object} [options] 匹配选项
* @param {number = 0} [options.matchedOffset] 匹配的matchedRoute的(向前)偏移量
* @param {string} [commonPageName] 公共路由的meta名称,如果commonPageName不为空并且currentRoute的meta中该名称的属性值为true,并且currentRoute.query.redirect不为空,则将会从currentRoute.query.redirect中解析matchedRoute
* @param {boolean = true} [options.watch] 是否监听路由变化
* @param {number|boolean = false} [options.delay] 路由发生变化时是否异步通知路由变更
* @param {boolean = true} [options.ignoreSamePath] 路由发生变化前后的路由fullPath相同,则不触发组件重新渲染
* @return {MatchRoute}
**/
const useMatchedRoute = (
defaultRouter?: ReactViewRouter|null,
options?: {
matchedOffset?: number,
watch?: boolean,
delay?: boolean|number,
ignoreSamePath?: boolean
}
) => MatchedRoute
```
### useMatchedRouteIndex
获取当前层级获取当前层级索引,函数签名如下:
```javascript
/**
* @param {ReactViewRouter} [defaultRouter] 默认的路由管理组件,当不传时它会根据上下文来寻找
* @param {number} [matchedOffset] 匹配的matchedRoute的(向前)偏移量,默认值为0
* @return {number}
**/
const useMatchedRouteIndex = (matchedOffset?: number = 0) => number
```
### useRouterView
获取当前层级的RouteView实例,函数签名如下:
```javascript
/**
* @return {RouterView}
**/
const useRouterView = () => RouterView
```
### useRouteGuardsRef
该方法封装了`useImperativeHandle` hooks,你可以通过该方法注册路由守卫。
```javascript
/**
* @param {Ref} ref 通过React.forwardRef获取的ref
* @param {T|(() => T)} guards 路由守卫对象,支持beforeRouteLeave、beforeRouteResolve、afterRouteLeave、beforeRouteUpdate守卫
* @param {DependencyList} deps 传给useImperativeHandle的deps
* @return {void}
**/
function useRouteGuardsRef(
ref: Ref|undefined,
guards: T|(() => T),
deps: DependencyList = []
): void
```
示例:
```js
import React from 'react';
import { useRouteGuardsRef } from 'react-view-router';
import modals from '~/utils/modals';
const Test = React.forwardRef((props, ref) => {
useRouteGuardsRef(ref, {
async beforeRouteLeave(to, from, next) {
console.log('Test beforeRouteLeave', to, from);
try {
await modals.confirm({ content: '确定要离开吗?' });
next();
} catch (ex) {
next(false);
}
},
beforeRouteUpdate(to, from) {
console.log('Test beforeRouteUpdate', to, from);
},
});
return (
something
);
});
export default Test;
```
注意:不要将`useRouteGuardsRef`和`useImperativeHandle`在一个函数组件中混用。
### useRouteChanged
为指定的`router`注册一个路由变更回调事件,函数签名如下:
```ts
/**
* @return {RouterView}
**/
const useRouteChanged = (router: ReactViewRouter, onChange: onRouteChangeEvent) => void
```
示例:
```js
import { useRouter, useRouteChanged } from 'react-view-router';
const router = useRouter();
useRouteChanged(router, (route) => {
const path = route.matched[0] && route.matched[0].subpath;
if (path !== activeTab && tabs.some((tab) => tab.key === path)) {
setActiveTab(path);
}
});
```
### useViewActivate
当当前路由组件启用了keepAlive后,并且在再次进入时会会触发激活事件;
```ts
interface KeepAliveEventObject {
type: keyof RouterViewEvents,
router: ReactViewRouter,
source: RouterView,
target: MatchedRoute,
to: MatchedRoute|null,
from: MatchedRoute|null,
}
type KeepAliveChangeEvent = (event: KeepAliveEventObject) => void;
/**
* @return {RouterView}
**/
const useViewActivate = (onEvent: KeepAliveChangeEvent) => void
```
示例:
```js
import { useViewActivate } from 'react-view-router';
useViewActivate((event) => {
// dosomething
});
```
### useViewDeactivate
当当前路由组件启用了keepAlive后,等离开当前路由时会触发失活事件;
```ts
interface KeepAliveEventObject {
type: keyof RouterViewEvents,
router: ReactViewRouter,
source: RouterView,
target: MatchedRoute,
to: MatchedRoute|null,
from: MatchedRoute|null,
}
type KeepAliveChangeEvent = (event: KeepAliveEventObject) => void;
/**
* @return {RouterView}
**/
const useViewDeactivate = (onEvent: KeepAliveChangeEvent) => void
```
示例:
```js
import { useViewDeactivate } from 'react-view-router';
useViewDeactivate((event) => {
// dosomething
});
```
### useRouteTitle
遍历路由配置,检索出组件当前所在层级的路由配置中`meta.title`、`meta.visible`过滤出来的信息,其中`meta.title`、`meta.visible`可以是一个函数。你可以根据该信息来创建菜单、标签页等。函数签名如下:
```ts
// `meta.title`、`meta.visible`可以是boolean值,也可以下面这样的函数
type RouteMetaFunction = (route: ConfigRoute, routes: ConfigRouteArray, props: {
router?: ReactViewRouter|null,
level?: number,
maxLevel?: number,
refresh?: () => void
[key:string]: any
}) => T;
type RouteTitleInfo = {
title: string;
path: string;
meta: Partial;
route: ConfigRoute;
children?: RouteTitleInfo[];
};
type filterCallback = (r: ConfigRoute, routes: ConfigRouteArray, props: {
router: ReactViewRouter
level: number,
maxLevel: number,
refresh: () => void,
title?: string,
visible?: boolean
}) => boolean;
type RouteTitleProps = {
// useRouteTitle的最大检索层级
maxLevel?: number,
// 对过滤出来的title信息进行自定义的过滤
filter?: filterCallback,
// 指定filter依赖的ConfigRoute中的meta参数名,以便它们更新时可以触发titles的更新
filterMetas?: string[],
/**
* 是否是手动模式,当为true时,第一次调用useRouteTitle时不会主动检索ConfigRoute,直到你调用一次refreshTitles后,
* 可以通过该参数实现异步展示菜单、标签栏等方案
**/
manual?: boolean,
// 匹配的matchedRoute的(向前)偏移量,默认值为0
matchedOffset?: number;
// 公共页面meta的key值,默认为'commonPage'。即当某个匹配路由的meta中包含commonPage: true时,并且router.currentRoute.query.redirect不为空时,解析路由将会改为从router.currentRoute.query.redirect重新解析titles
commonPageName?: string;
}
type RouteTitleResult = {
titles: RouteTitleInfo[];
setTitles: (titles: RouteTitleInfo[]) => void;
currentPaths: string[];
setCurrentPaths: (currentPaths: string[]) => void;
refreshTitles: () => void;
}
/**
* @param {RouteTitleProps} props 参数
* @param {ReactViewRouter} defaultRouter 默认的路由实例
* @param {DependencyList} deps 传给useRouteTitle的deps
* @return {RouteTitleResult}
**/
function useRouteTitle(
props: RouteTitleProps = {},
defaultRouter?: ReactViewRouter,
deps: any[] = []
): RouteTitleResult;
```
左侧菜单示例:
```js
import React, { useMemo, useEffect } from 'react';
import {
useRouter, useRouteTitle,
} from 'react-view-router';
import { observer } from 'mobx-react';
import { LeftMenu } from '@/ui';
import store from '@/store';
const MainLeft = observer(() => {
const { companyId } = store.state.company;
const router = useRouter();
const {
titles,
currentPaths: currentMenus,
refreshTitles,
} = useRouteTitle({
// 从当前组件所在的路由层级再向下2级开始查找匹配titles
maxLevel: 2
});
const menus = useMemo(() => {
const getMenus = (list = []) => list.map((item) => {
const { title, meta, path } = item;
return {
text: title,
key: path,
icon: meta.icon ? : null,
children: getMenus(item.children),
};
});
return getMenus(titles);
}, [titles]);
useEffect(() => {
if (titles.length) refreshTitles();
}, [companyId]);
const parentPaths = currentPaths.length > 1
? currentPaths.slice(0, currentPaths.length - 1)
: currentPaths;
const currentPath = currentPaths.length ? currentPaths[currentPaths.length - 1] : null;
return (
router.push(path)}
/>
);
});
export default MainLeft;
```
标签栏示例:
```js
import React from 'react';
import router from '@/history';
import { useRouter, RouterView, useRouteTitle } from 'react-view-router';
import { Tabs } from '@/ui';
const { TabPane } = Tabs;
function MainHeader(props) {
const router = useRouter();
const {
titles,
currentPaths: [currentPath],
} = useRouteTitle({ maxLevel: 1 }, router);
return (
router.replace(path)}
>
{
titles.map((tab) => (
))
}
);
}
export default MainHeader;
```
## ReactViewLike集成
`react-view-router`可以作为`ReactVueLike`的插件来使用:
```js
import vuelike from '@/vuelike';
import ReactViewRouter from 'react-view-router';
const router = new ReactViewRouter({
basename: '', // app的basename,若页面路由是在/app/下面,则base的值应该为"/app/"
mode: 'hash', // 路由类型 browser|memory|hash, default:hash
routes: [] // 路由配置数组,也可以使用router.use方法来初始化
});
vuelike.use(router);
```
这样既可将`router`注册为ReactVueLike的插件。注册后,将有以下功能:
### 组件级的路由事件
```js
import React from 'react';
import ReactVueLike from 'react-vue-like';
class EmployeeManager extends ReactVueLike.Component {
beforeRouteEnter(to, from, next) {
next();
}
beforeRouteLeave(to, from, next) {
next();
}
beforeRouteResolve(to, from) {
}
afterRouteLeave(to, from) {
}
beforeRouteUpdate(to, from) {
}
render() {
return (
);
}
}
export default EmployeeManager;
```
### 注入对象
在`ReactVueLike.Component`组件实例中,可以取到:
- `$router` - 当前路由管理实例
- `$route` - object, 当前路由信息,等同于`router.currentRoute`
- `$matchedRoute` object, 当前匹配的子路由信息
- `$routeIndex` number, 当前匹配的子路由的索引
三者的关系是:`$route.matched[$routeIndex] === $matchedRoute`。
下面是一个“通过从路由元信息中读取tab标签页信息并渲染”的一个示例:
```js
import React from 'react';
import ReactVueLike from 'react-vue-like';
class EmployeeManager extends ReactVueLike.Component {
static computed = {
active() {
const matched = this.$route.query.redirect
? this.$router.getMatched(this.$route.query.redirect)
: this.$route.matched;
const match = matched[this.$routeIndex + 1];
return (match && match.subpath) || 'roster';
},
tabs() {
return this.$matchedRoute.config.children
? this.$matchedRoute.config.children.filter((r) => r.meta.title && !r.meta.hideTab).map((r) => ({
key: r.subpath,
label: r.meta.title,
badge: Boolean(r.meta.badge)
}))
: [];
},
}
handleTabChanged(v) {
const path = `${this.$matchedRoute.path}/${v}`;
if (this.$route.path === path) return;
this.$router.replace(path);
}
render() {
return (
{ this.tabs.map((tab) => )}
);
}
}
export default EmployeeManager;
```
### 监听路由变化
通过`ReactVueLike.Component`的`watch`功能可以监听路由变化来做一些事情。
示例:
```js
import React from 'react';
import ReactVueLike from 'react-vue-like';
class MainSider extends ReactVueLike.Component {
static watch = {
$route(newVal, oldVal) {
if (!newVal || !oldVal) return;
// 路由变化时,更新左侧菜单信息
if (newVal.fullPath !== oldVal.fullPath) this.updateList(newVal);
},
}
static methods = {
updateList(route) {
...
},
}
}
export default MainSider;
```
## 路由转场动效
你可以通过`import RouterView from 'react-view-router/transition'`引用支持路由跳转动效的`RouterView`来为页面添加简单的转场动效。目前支持`fade|slide|carousel`三种动效:
```js
import React from 'react';
// import { RouterView } from 'react-view-router';
import RouterView from 'react-view-router/transition';
import router from '@/history';
function App() {
return (
);
}
export default App;
```
用法和普通的`RouterView`一样,只是多添加了`transition`、`transitionPrefix`、`transitionZIndex`、`routerView`四个额外属性:
```ts
interface TransitionRouterViewProps extends RouterViewProps {
transition?: TransitionName | {
name: TransitionName,
zIndex?: number,
containerStyle?: React.HTMLAttributes,
containerTag?: string | React.ComponentType | React.ForwardRefExoticComponent
};
transitionPrefix?: string;
transitionZIndex?: number;
routerView?: RouterViewComponent
}
```
- `transition` - 动效的名称,目前支持`slide`、`fade`两种动效。它也可以是一个对象。
- `transitionPrefix` - 动效的`className`前缀,默认为`react-view-router-`。如果你修改了该值,则动效的样式需要由你自己来提供;
- `transitionZIndex` - 进场/离场页面的`zIndex`,默认为1000。若当前是`slide`动效,并且当前页面中存在zIndex大于1000的元素时,你可以通过设置`transitionZIndex`为更高的值来避免该元素穿透转场页面。
## 中台模块中路由处理
中台模块如果需要配置路由时,需要将它的路由添加到宿主项目的路由地址后面追加,`react-view-router`也支持这种模式的开发。
1. 配置路由实例为手动模式:
```js
import ReactViewRouter from 'react-view-router';
import routes from './routes';
const router = new ReactViewRouter({
manual: true,
routes
});
export default router;
```
2. 在模块初始化/销毁时启动路由监听
```js
import router from '@/history';
export default {
bootstrap({ basename, routeMode }) {
...
router.start({ basename, routeMode });
...
},
unmount() {
...
router.stop();
...
}
}
```
或者在组件中:
```js
import React from 'react';
import { useManualRouter, RouterView } from 'react-view-router';
import router from '@/history';
/**
* 全局的路由拦截事件
* @type {import('react-view-router').RouteBeforeGuardFn}
**/
function beforeEach(to, from, next) {
next();
}
function App({ basename, routeMode }) {
useManualRouter(router, { basename, routeMode });
return
}
export default App;
```
## NOTE
1. `react-view-router`不依赖`react-vue-like`,可以独立使用
2. 如果路由组件是`Class Component` (不是 `Function Component`), 则在`beforeRouteUpdate`,`beforeRouteLeave`,`afterRouteLeave` 组件的守卫函数都会绑定到 `this`变量,它指向当前组件实例;