【前言】
之前使用过vue的的脚手架vue-cli,对比现在react的脚手架create-react-app,惊叹在官方维护方面,vue确实做得比react更好(在开发体验方面)。create-react-app这个脚手架对比vue-cli的脚手架简直一穷二白,包括官方文档也一样。react的路由文档写得和vue路由的文档相去甚远。但是,在使用react的过程中,也体会到了一个好处,就是react在开发的过程中让你跟接近“原理”的去开发,你经常会出现这样的感受——原来vue这个模块的工作原理原来是这样的......好了,废话不多说,下面进入正题。
【正文】
其实不管是vue还是react,其路由懒加载的实现得益于wepack的异步模块打包,webpack会对代码中异步引入的模块单独打包一份,直到真正调用的时候才去服务端拿。典型的例子就是下面这样一段代码
const a = () => import('./testComponent')
右边的表达式如果返回一个webpack.require.ensure
对象(最终应该是一个promise对象),这个其实就是webpack异步模块打包方法,只有在模块真正调用的时候才会加载。
在vue-router中我们只要在路由配置的component
中直接传入() => import('./testComponent')
即可。而在react的路由中,它路由配置中的component必须传入react 的component对象。那么我们可以在react的生命周期中做文章。我们新建一个高阶组件,在这个高阶组件一个react类组件中的componentWillMount
中传入() => import('./xxx组件')
并传入到该react组件的state中。那么我们就可以在render中去调用传入的组件。
具体做法看例子
项目目录结构 2019-06-28_192344.png
//lazyLoad.js
import React from 'react';
export default function lazyLoad(componentfn) {
class LazyloadComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
component: null
}
}
async componentWillMount() {
const {default: component} = await componentfn();
this.setState({component})
}
render() {
const C = this.state.component;
return C ? <C {...this.props}/> : null;
}
}
return LazyloadComponent;
}
//router.js
import React from 'react'
import { Route, HashRouter } from 'react-router-dom'
import lazyLoad from '../common/lazyLoad'
const A = lazyLoad(() => import("../components/a"))
const B = lazyLoad(() => import("../components/b"))
const C = lazyLoad(() => import("../components/c"))
const D = lazyLoad(() => import("../components/d"))
const RouterView =
<HashRouter>
<Route path={'/'} component={A} exact={true} key={1} />
<Route path={'/b'} component={B} exact={true} key={2} />
<Route path={'/c'} component={C} exact={true} key={3} />
<Route path={'/d'} component={D} exact={true} key={4} />
</HashRouter>
export default RouterView
//index.js
import ReactDOM from 'react-dom';
import './index.css';
import * as serviceWorker from './serviceWorker';
import RouterView from './router/router'
ReactDOM.render(
RouterView,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
然后随便在一个渲染组件中写几个路由
//a.js
import React from 'react';
import {Link } from 'react-router-dom'
class A extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef()
this.showref = this.showref.bind(this)
}
render() {
return (
<div>
<Link to='/b'>b</Link>
<Link to='/c'>c</Link>
<Link to='/d'>d</Link>
</div>
)
}
}
export default A
网友评论