Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
fengyuanzemin committed May 13, 2018
1 parent d3509b4 commit 3a5069e
Show file tree
Hide file tree
Showing 4 changed files with 343 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ tags: readme

后来就建了自己的博客,每个月交钱给阿里云。

还是打算在上面记录一些技术、生活、感想。
打算在上面记录一些技术、生活、感想。

各位看官,请~
128 changes: 128 additions & 0 deletions react-router 4 嵌套路由实现.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
title: react-router 4 嵌套路由实现
date: 2018-05-13
tags: Javascript
---

# 问题

我们没用使用官方提供的react-router-config,而是自己实现了一套。问题在于,自己实现的不支持嵌套路由,于是我周末想了想,进行了改造

<!--more-->

## route
想支持却没有嵌套功能的路由:

```js
const RoutesConfig = {
'/index': {
component: asyncComponent(() => import('../containers/Home')),
},
'/a': {
component: asyncComponent(() => import('../containers/A')),
},
};
```
## usage

```jsx
<Switch>
{
getRoutes(match.path, routesConfig).map((item) => {
return (<Route
path={item.path}
key={item.key}
component={item.component}
/>
);
})
}
</Switch>
```

## map

```js
export function getRoutes(path, routesConfig) {
const routes = Object.keys(routesConfig).filter((routePath) =>
routePath.indexOf(path) === 0 && routePath !== path);
const routesArr = routes.map((item, key) => {
return {
path: item,
key,
component: routesConfig[item].component,
};
});
return routesArr;
}
```

# 解决
首先,我觉得router的配置文件应该是一个数组,这样有顺序。其次,我看了上面 map 部分的代码,其实也是把它转化成数组来操作的。(我在尝试之后觉得用对象实在太麻烦,每用一次就要转义一次)。既然如此,我就直接用数组了。

## route

```js
const RoutesConfig = [
{
path: '/index',
component: asyncComponent(() => import('../containers/Home')),
},
{
path: '/a',
component: asyncComponent(() => import('../containers/A')),
children: [
{
path: '/a/b',
component: asyncComponent(() => import('../containers/A/B')),
},
],
},
];
```
既然要实现嵌套路由,所以嵌套的部分必然也是通用的数据结构,这样才能进行调用。

## check

原先的 map 我发现和 usage 部分有点重复,所以只保留一个校验功能

```js
export const routeCheck = (path, routesConfig) => routesConfig.filter((item) =>
item.path.indexOf(path) === 0 && item.path !== path);
```

## Usage

```js
renderRoute = (routes) => {
if (!Array.isArray(routes)) {
return null;
}
return routes.map((item) => {
if (item.children && item.children.length > 0) {
return (<div
key={`${item.key}-has-children`}
>
<Route
path={item.path}
key={item.key || item.path}
component={item.component}
/>
<Switch>
{
this.renderRoute(item.children)
}
</Switch>
</div>);
}
return (<Route
path={item.path}
key={item.key || item.path}
component={item.component}
/>);
});
};
```

然后,问题就顺利解决了

126 changes: 126 additions & 0 deletions react-router 4 按需加载.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
title: react-router 4 按需加载
date: 2017-08-20
tags: [Javascript, react-router, react]
---

根据官网文档:[https://reacttraining.com/react-router/web/guides/code-splitting](https://reacttraining.com/react-router/web/guides/code-splitting)

首先得安装bundle-loader

```sh
yarn add bundle-loader
```
<!--more-->

根据官网文档,定义了一个Bundle的组件

```jsx
import React, { Component } from 'react';

export default class Bundle extends Component {
state = {
// short for "module" but that's a keyword in js, so "mod"
mod: null,
};

componentWillMount() {
this.load(this.props);
}

componentWillReceiveProps(nextProps) {
if (nextProps.load !== this.props.load) {
this.load(nextProps);
}
}

load(props) {
this.setState({
mod: null,
});
props.load((mod) => {
this.setState({
// handle both es imports and cjs
mod: mod.default ? mod.default : mod,
});
});
}

render() {
return this.state.mod ? this.props.children(this.state.mod) : null;
}
}
```
加载组件的时候使用bundle-loader加载,并且将组件传入Bundle中,最后渲染使用renderRoutes方法就可以了

```js
import React from 'react';
import {
BrowserRouter as Router,
} from 'react-router-dom';
import { renderRoutes } from 'react-router-config';

/* eslint-disable */
import Index from 'bundle-loader?lazy&name=index!app/components/Demo/Index';
import IndexContainer from 'bundle-loader?lazy&name=index!app/components/Demo/IndexContainer';
import ListContainer from 'bundle-loader?lazy&name=list!app/components/Demo/ListContainer';
import NotFound from 'bundle-loader?lazy&name=notfound!app/components/Demo/NotFound';

/* eslint-enable */

import Bundle from 'app/components/Demo/Bundle';


const routes = [
{
component: (props) => (
<Bundle load={Index}>
{(Component) => <Component {...props}/>}
</Bundle>
),
routes: [
{
path: '/',
exact: true,
component: (props) => (
<Bundle load={IndexContainer}>
{(Component) => <Component {...props}/>}
</Bundle>
),
},
{
path: '/list/:moduleName',
exact: true,
component: (props) => (
<Bundle load={ListContainer}>
{(Component) => <Component {...props}/>}
</Bundle>
),
},
{
path: '/form/:moduleName/:id',
exact: true,
component: (props) => (
<Bundle load={FormContainer}>
{(Component) => <Component {...props}/>}
</Bundle>
),
},
{
path: '/*',
component: (props) => (
<Bundle load={NotFound}>
{(Component) => <Component {...props}/>}
</Bundle>
),
},
],
},
];

export default (
<Router>
{renderRoutes(routes)}
</Router>
);
```
88 changes: 88 additions & 0 deletions react-router-config 使用.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: react-router-config 使用
date: 2017-08-25
tags: [react, Javascript, react-router]
---

react-router升级4之后,要想使用config方式的路由模式,要么自己写一个函数遍历config,要么使用react-router-config

[https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config)

react-router-config还是beta版本,其中有 renderRoutes 方法,其作用就是遍历你的routes,返回<Router>和<Switch>

<!--more-->

```js
import React from 'react'

import Switch from 'react-router/Switch'

import Route from 'react-router/Route'

const renderRoutes = (routes, extraProps = {}) => routes ? (

<Switch>

{routes.map((route, i) => (

<Route key={i} path={route.path} exact={route.exact} strict={route.strict} render={(props) => (

<route.component {...props} {...extraProps} route={route}/>

)}/>

))}

</Switch>

) : null

export default renderRoutes
```

而对于config文件,是这样的写法

```js
const routes = [
{
component: Index,
routes: [
{
path: '/',
exact: true,
component: IndexContainer,
},
{
path: '/list/:moduleName',
exact: true,
component: ListContainer,
},
{
path: '/*',
component: NotFound,
},
],
},
];
```
在使用时,需要用renderRoutes(routes)

而且,如果是嵌套路由,那么父路由处也需要写这个渲染函数

比如在Index 组件里

```js
import React from 'react';
import { renderRoutes } from 'react-router-config';

export default class extends React.PureComponent {

render() {
return (
<div className="index-page">
{renderRoutes(this.props.route.routes)}
</div>
);
}
}
```

0 comments on commit 3a5069e

Please sign in to comment.