美文网首页web前端开发
基于webpack4.x和react-router5.x实现路由

基于webpack4.x和react-router5.x实现路由

作者: 李牧敲代码 | 来源:发表于2019-06-29 00:00 被阅读0次

【前言】

之前使用过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>&nbsp;
                <Link to='/c'>c</Link>&nbsp;
                <Link to='/d'>d</Link>&nbsp;
            </div>
        )
    }
} 

export default A

看效果

test3.gif

【完】

相关文章

网友评论

    本文标题:基于webpack4.x和react-router5.x实现路由

    本文链接:https://www.haomeiwen.com/subject/giiecctx.html