• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >JavaScript > react按需加载

react按需加载

作者:幸福那一刻 字体:[增加 减小] 来源:互联网 时间:2017-08-31

幸福那一刻通过本文主要向大家介绍了react等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

原文链接:http://blog.csdn.net/mjzhang1993/article/details/54913942点击打开链接

 

react-router webpack 按需加载,与路由权限控制

说明

当网站规模越来越大,通过webpack 打包后的 React 项目也会越来越大,这会导致首页渲染时间变长,影响用户体验,webpack 提供了一种按需加载的方式,需要结合 react-router 使用,他会将代码拆分成多个小包,需要哪个部分就加载响应的包。

webpack 配置

首先需要对 config 文件修改一下,如下

  output: {
    path: path.join(__dirname, 'dev'),  // 输出路径
    filename: '/js/bundle.js',  // 输出文件名
    publicPath: path.join(__dirname, 'dev'), // 必填项
    chunkFilename : '/js/routes/[name].chunk.js?[chunkhash:10]', // 按需加载输出的文件名
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

路由配置页(app/js/routes.js)

react 按需加载,关键是让路由动态加载组件,react-router 提供了一个属性 getComponent ,它与 component 属性一样,但是是异步的,当路由匹配时才会调用这个方法,常用于代码分割; 
相关内容查看 API文档

webpack 为我们提供了一个按需加载函数 require.ensure(dependencies, callback, chunkName),

  • dependencies : 依赖的模块数组
  • callback : 回调函数,该函数调用时会传入一个 require 参数
  • chunkName : 模块名,用于构建时生成文件名

更多了解,查看官方文档

一般写法
    /*
       app/js/routes.js
       路由配置文件
    */

    import React from 'react';
    import { Route, IndexRoute} from 'react-router';
    // 引入容器组件
    import App from './containers/App';

    export default (
        <Route path="/" component={App}>
          <IndexRoute getComponent={(location, cb) => {
                require.ensure([], require => {
                   cb(null, require('./containers/Login.js').default)
                },'login');
             }} />
          <Route path="home"
             getComponent={(location, cb) => {
                require.ensure([], require => {
                   cb(null, require('./containers/Home.js').default)
                },'home');
             }} />
          <Route path="login" getComponent={(location, cb) => {
                require.ensure([], require => {
                   cb(null, require('./containers/Login.js').default)
                },'login');
             }} />
        </Route>
    );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

注意:cb(null, require('./containers/Login.js').default) 因为我用 es6 的 export default 导出的组件,所以 require 之后要加上 default,如果使用 module.export 导出组件 则不需要加 default

拆分写法

以上写法在 路由层级或者数量较多的时候会比较臃肿,所以还需要对路由进行拆分

路由拆分,需要对目录结构做一下改变,在js 文件夹下添加 routes 路由配置文件夹

   |---js
    |    |---actions
    |    | 
    |    |---components
    |    |
    |    |---containers
    |    |
    |    |---reducers
    |    |
    |    |---store
    |    |    
    |    |---routes
    |    |     |---login.js                 // 主路由的下一级路由
    |    |     |---login                    // login 路由的下一级路由目录
    |    |---constants.js                   // 静态常量
    |    |---index.js                       // 项目入口文件
    |    |---routes.js                      // 路由配置主文件
    |
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

routes.js 路由配置的主文件

    const routes = {
       path : '/',                  // 将匹配的路由,对应标签中的 path 属性
       indexRoute: {                // 设置默认显示页面,对应标签中的 IndexRoute 组件
          getComponent(nextState, cb) { 
             require.ensure([], (require) => {  
                cb(null, require('./containers/Login').default);
             }, 'Login');
          }
       },
       // childRoutes:[]                      // 子 route 的一个数组,与在 JSX route 配置中的 children 一样。
       getChildRoutes(partialNextState, cb) { // 与 childRoutes 一样,但是是异步的,并且可以接收 partialNextState(location 信息)
         require.ensure([], (require) => {
           cb(null, [
              require('./routes/login'),
              require('./routes/home'),
              require('./routes/error')
           ])
         })
       },
       getComponent(nextState, cb) {        // 定义对应的组件,对应标签中的 component 属性,但是是异步的,路由匹配时才会调用这个方法
          require.ensure([], (require) => { // require.ensure : webpack 提供的按需加载方法
             cb(null, require('./containers/App').default);
          }, 'App');
       }

    }

    export default routes;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

js/routes/home.js 路由分支

    module.exports = {
      path: 'home',

      getChildRoutes(partialNextState, cb) {
        require.ensure([], (require) => {
          cb(null, [
            require('./home/page'),
            require('./home/student'),
            require('./home/admin')
          ])
        })
      },

      getComponent(nextState, cb) {
        require.ensure([], (require) => {
          cb(null, require('../containers/Home').default)
        }, 'Home')
       }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

路由权限控制

基本思路 : 每当指定路由要发生改变,就使用一个中间服务,介于上一级路由和将要到达路由之间启动,来判断我们是否有进入这个路由的权限,React 中的 <Route /> 提供了一个 onEnter方法,表示正要进入这个路由,在这里判断进入权限,可以修改要进入的页面

<Route path="home"
    getComponent={(location, cb) => {
        require.ensure([], require => {
            cb(null, require('./containers/Home.js').default)
        },'home');
    }} onEnter={request}/>

function request(nextState, replace, next){
   let auth = nextState.location.query.auth;
   if(auth === 'home'){
      next();
   } else if (auth === 'other') {
      replace('/other');
      next();
   } else {
      replace('/');
      next();
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

注:nextState : 表示跳转后的location 信息;replace 用于 更改下一个进入的页面地址,但是不会跳转;next : 用于跳转页面,没有其他操作则显示当前路由对应页面

如果使用路由拆分,如下

    module.exports = {
        path: 'home',

        getChildRoutes(partialNextState, cb) {
            require.ensure([], (require) => {
              cb(null, [
                require('./home/page'),
                require('./home/student'),
                require('./home/admin')
              ])
            })
        },

        getComponent(nextState, cb) {
            require.ensure([], (require) => {
              cb(null, require('../containers/Home').default)
            }, 'Home')
        },

        onEnter: (nextState, replace, next) => {
          console.log(nextState.location.state);
          let isAuth = nextState.location.state.isAuth;
          if (isAuth === 'student' || isAuth === 'teacher' || isAuth === 'admin') {
             next();
          } else {
             replace('/error');
             next();
          }
       }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

 

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

相关文章

  • 2017-05-11利用JS实现简单的日期选择插件
  • 2017-05-11jQuery ajax实现省市县三级联动
  • 2018-01-28js 控制 history 返回事件
  • 2017-05-11webpack配置文件和常用配置项介绍
  • 2017-05-11prototype与__proto__区别详细介绍
  • 2017-05-11完美解决spring websocket自动断开连接再创建引发的问题
  • 2017-05-11jQuery插件扩展操作入门示例
  • 2017-05-11原生JS轮播图插件
  • 2017-11-15JS 编码,解码
  • 2017-05-11JavaScript数据结构之二叉树的遍历算法示例

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • JavaScript实现两个select下拉框选项左移右移
    • NodeJS遍历文件生产文件列表功能示例
    • 详解angular2采用自定义指令(Directive)方式加载jquery插件
    • 使用ionic在首页新闻中应用到的跑马灯效果的实现方法
    • 微信小程序页面传值实例分析
    • jQuery html表格排序插件tablesorter使用方法详解
    • input输入密码变黑点密文的实现方法
    • jquery使用EasyUI Tree异步加载JSON数据(生成树)
    • js实现二级导航功能
    • jQuery时间验证和转换为标准格式的时间格式

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有