从零开始,构建自己的react项目,二增加多级路由和按需加载组件

上次刚讲完使用webpack从零搭建一个空的React项目,现在接下来开始完善这个架子,增加按需加载的功能和多级路由的功能,关于redux的功能将在下次开始添加。

组件的按需加载

  • 组件按需加载,对于一个比较复杂的页面来说,是一个不错的提升页面加载性能的方法。
  • 首先想到的就是React官方提供的lazy方法,这个lazy有个坑,就是必须要结合Suspense来使用,单独使用会直接报错。
  • 由于可能页面里很多地方都需要使用按需加载,所以讲其简单的封装抽离成一个公共的按需加载方法。
  • 代码如下:
    import React, { Suspense, lazy } from 'react';
    
    /**
     * 通用的按需加载组件的方法
     * 使用如下
     *  const HelloWorld = AsyncComponent(() => import('Components/test/HelloWorld'));
     */
    const AsyncComponent = (importFunc) => {
    
      const Component = lazy(importFunc);
    
      return (props) => (
        <Suspense
          fallback={<div>loading...</div>}
        >
          <Component {...props} />
        </Suspense>
      )
    }
    

多级路由的引入

  • 引入路由管理,是针对项目中存在多个不同的,或者多层级的页面的一种比较好的解决方法,没有路由也不是不可以做,就是管理起来不是很方便。
  • 要注意一下,当react-router升级到4.0以后就不再支持Route的多级嵌套了,所以每次存在子路由的时候,可能需要一个公共的父级页面来专门渲染子路由。
  • 首先是在routes文件夹下添加对应的路由配置文件。
    import { AsyncComponent } from 'Utils/component';
    
    const Main = AsyncComponent(() => import('Pages/main'));
    const Home = AsyncComponent(() => import('Pages/Home'));
    const HelloWorld = AsyncComponent(() => import('Components/test/HelloWorld'));
    
    const routes = [
      {
        path: '/',
        component: Main,
        exact: true // 严格匹配,保证刚进来的时候直接展示首页
      },
      {
        path: '/',
        component: Home, // 模糊匹配,进入子路由的时候,就会走这里
        children: [
          {
            path: '/hello',
            component: HelloWorld
          }
        ]
      }
    ];
    
    export default routes;
    
  • 然后是多路由的渲染,我将其抽离出来,方便后续可以增加功能,比如可以将全局的search参数做处理后传入路由对应的组件,方便使用
    /**
    * 路由遍历功能
    */
    const renderRoutes = (routes) => {
    
      return routes.map((route, index) => {
        const { children, path, exact = false } = route;
        /**
          * 可以在这里做一些全局的处理,把search参数处理之后传进route.component,这样就不用每个页面都要对search参数去做一次处理
          */
        const search = location.search;
        const query = searchToQuery(search); // 将search字符串变成一个对象,然后传入 
        return (
          <Route
            path={path}
            exact={exact}
            key={`${route.path}-${index}`}
            render={props => <route.component {...props} routes={children} urlQuery={query} />}
          />
        )
      })
    }
    
  • 在入口文件index.js中使用路由。
    import React from "react";
    import ReactDOM from "react-dom";
    import { Router } from 'react-router';
    import { createBrowserHistory } from 'history';
    
    import { renderRoutes } from 'Utils/component';
    import routes from 'Routes';
    
    const browserHistory = createBrowserHistory(); 
    // 使用browserHistory有一个注意点,本地开发时,需要将webpack的config.devServer.historyApiFallback设置为true。不然会出现你输入路径时,把路径当做接口来访问,而不是当做路由。
    
    function render() {
      ReactDOM.render(
        <Router history={browserHistory}>
          {
            renderRoutes(routes)
          }
        </Router>,
        document.getElementById("root")
      );
    }
    
    render();
    
  • 至此,我们的异步加载组件和多级路由全部加入,下一次就是配置redux。

小结

  • 到目前为止,这个架子已经可以满足一些小型的业务需求,如果对于庞大的业务量,最好还是把redux的状态管理给加上,不然全局状态会很乱。
  • 源码路径,https://github.com/810307015/ReactDemo,有兴趣可以看看。
  • 看到这里的小伙伴们,给我点个赞,留个言啊。