React router动态加载组件之适配器模式的应用详解

前言

本文讲述怎么实现动态加载组件,并借此阐述适配器模式。

一、普通路由例子

import Center from 'page/center';
import Data from 'page/data';

function App(){
 return (
  <Router>
   <Switch>
   <Route exact path="/" render={() => (<Redirect to="/center" />)} />
   <Route path="/data" component={Data} />
   <Route path="/center" component={Center} />
   <Route render={() => <h1 style={{ textAlign: 'center', marginTop: '160px', color:'rgba(255, 255, 255, 0.7)' }}>页面不见了</h1>} />
   </Switch>
  </Router>
 );
}

以上是最常见的React router。在简单的单页应用中,这样写是ok的。因为打包后的单一js文件bundle.js也不过200k左右,gzip之后,对加载性能并没有太大的影响。

但是,当产品经历多次迭代后,追加的页面导致bundle.js的体积不断变大。这时候,优化就变得很有必要。

二、如何优化

优化使用到的一个重要理念就是——按需加载。

可以结合例子进行理解为:只加载当前页面需要用到的组件。

比如当前访问的是/center页,那么只需要加载Center组件即可。不需要加载Data组件。

业界目前实现的方案有以下几种:

•react-router的动态路由getComponent方法(router4已不支持)
•使用react-loadable小工具库
•自定义高阶组件进行按需加载

而这些方案共通的点,就是利用webpack的code splitting功能(webpack1使用require.ensure,webpack2/webpack3使用import),将代码进行分割。

接下来,将介绍如何用自定义高阶组件实现按需加载。

三、自定义高阶组件

3.1 webpack的import方法

webpack将import()看做一个分割点并将其请求的module打包为一个独立的chunk。import()以模块名称作为参数名并且返回一个Promise对象。

因为import()返回的是Promise对象,所以不能直接给<Router/>使用。

3.2 采用适配器模式封装import()

适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

当前场景,需要解决的是,使用import()异步加载组件后,如何将加载的组件交给React进行更新。
 方法也很容易,就是利用state。当异步加载好组件后,调用setState方法,就可以通知到。
 那么,依照这个思路,新建个高阶组件,运用适配器模式,来对import()进行封装。

3.3 实现异步加载方法asyncComponent

import React from 'react';
export const asyncComponent = loadComponent => (
 class AsyncComponent extends React.Component {
  constructor(...args){
   super(...args);
   this.state = {
    Component: null,
   };
   this.hasLoadedComponent = this.hasLoadedComponent.bind(this);
  }
  componentWillMount() {
   if(this.hasLoadedComponent()){
    return;
   }
   loadComponent()
    .then(module => module.default ? module.default : module)
    .then(Component => {
     this.setState({
      Component
     });
    })
    .catch(error => {
     /*eslint-disable*/
     console.error('cannot load Component in <AsyncComponent>');
     /*eslint-enable*/
     throw error;
    })
  }
  hasLoadedComponent() {
   return this.state.Component !== null;
  }
  render(){
   const {
    Component
   } = this.state;
   return (Component) ? <Component {...this.props} /> : null;
  }
 }
);
// 使用方式
const Center = asyncComponent(()=>import(/* webpackChunkName: 'pageCenter' */'page/center'));

如例子所示,新建一个asyncComponent方法,用于接收import()返回的Promise对象。

当componentWillMount时(服务端渲染也有该生命周期方法),执行import(),并将异步加载的组件,set入state,触发组件重新渲染。

3.4 释疑

•state.Component初始化

this.state = {
 Component: null,
};

这里的null,主要用于判断异步组件是否已经加载。

•module.default ? module.default : module

这里是为了兼容具名和default两种export写法。

•return (Component) ? <Component {...this.props} /> : null;

这里的null,其实可以用<LoadingComponent />代替。作用是:当异步组件还没加载好时,起到占位的作用。
this.props是通过AsyncComponent组件透传给异步组件的。

3.5 修改webpack构建

output: {
 path: config.build.assetsRoot,
 filename: utils.assetsPath('js/[name].[chunkhash].js'),
 chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
}

在输出项中,增加chunkFilename即可。

四、小结

自定义高阶组件的好处,是可以按最少的改动,来优化已有的旧项目。

像上面的例子,只需要改变import组件的方式即可。花最少的代价,就可以得到页面性能的提升。

其实,react-loadable也是按这种思路去实现的,只不过增加了很多附属的功能点而已。

以上所述是小编给大家介绍的React router动态加载组件之适配器模式的应用,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • react-router browserHistory刷新页面404问题解决方法

    使用React开发新项目时,遇见了刷新页面,直接访问二级或三级路由时,访问失败,出现404或资源加载异常的情况,本篇针对此问题进行分析并总结解决方案. 背景 使用webpack-dev-server做本地开发服务器时,正常情况只需要简单使用webpack-dev-server指令启动即可,但是当项目处于以下两种情况时,往往需要有嵌套路由和异步加载路由: 我们使用react-router这种路由库构建单页面应用路由: 使用html-webpack-plugin插件动态将加载js的<script>

  • 使用react-router4.0实现重定向和404功能的方法

    在开发中,重定向和404这种需求非常常见,使用React-router4.0可以使用Redirect进行重定向 最常用的就是用户登录之后自动跳转主页. import React, { Component } from 'react'; import axios from 'axios'; import { Redirect } from 'react-router-dom'; class Login extends Component{ constructor(){ super(); this.

  • 详解升级react-router 4 踩坑指南

    一.前言 上午把近日用React做的一个新闻项目所依赖的包升级到了最新的版本,其中从react-router(2.8.1)升级到react-router(4.1.2)中出现了很多问题, 故总结一下在升级过程中遇到的问题. 二.react-router,V4版本修改内容 1. 所有组件更改为从react-router-dom导入 之前的所有路由组件均是从react-router中导入,在我之前的项目中,导入相关组件如下: //v2 import {Router,Route,hashHistory}

  • 深入理解react-router@4.0 使用和源码解析

    如果你已经是一个正在开发中的react应用,想要引入更好的管理路由功能.那么,react-router是你最好的选择~ react-router版本现今已经到4.0.0了,而上一个稳定版本还是2.8.1.相信我,如果你的项目中已经在使用react-router之前的版本,那一定要慎重的更新,因为新的版本是一次非常大的改动,如果你要更新,工作量并不小. 这篇文章不讨论版本的变化,只是讨论一下React-router4.0的用法和源码. 源码在这里:https://github.com/ReactT

  • React-Router如何进行页面权限管理的方法

    前言 在一个复杂的SAP应用中,我们可能需要根据用户的角色控制用户进行页面的权限,甚至在用户进入系统之前就进行权限的控制.本文就此一权限控制进行讨论.本文假设读者了解React和React-Router的相关使用. 从传统的Router开始 一个传统的路由大概长下边这个样式,这是没有添加任何权限限制的. export default (store) => { const history = syncHistoryWithStore(hashHistory, store); return ( <

  • React Router基础使用

    React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单介绍其基础使用,更全面的可参考 指南 1. 它看起来像是这样 在页面文件中 在外部脚本文件中 2. 库的引入 React Router库的引入,有两种方式 2.1 浏览器直接引入 可以引用 这里 的浏览器版本,或者下载之后引入 然后就可以直接使用 ReactRouter 这个对象了,我们可能会使用到

  • react-router4 嵌套路由的使用方法

    react我自己还在摸索学习中,今天正好学习一下react-router4 嵌套路由的使用方法,顺便留着笔记 先直接贴代码 import React from 'react'; import ReactDOM from 'react-dom'; import { HashRouter as Router, Route, Switch} from 'react-router-dom'; import createBrowserHistory from 'history/createBrowserH

  • React-router 4 按需加载的实现方式及原理详解

    React-router 4 介绍了在router4以后,如何去实现按需加载Component,在router4以前,我们是使用getComponent的的方式来实现按需加载的,router4中,getComponent方法已经被移除,下面就介绍一下react-router4是入围和来实现按需加载的. 1.router3的按需加载方式 route3中实现按需加载只需要按照下面代码的方式实现就可以了. const about = (location, cb) => { require.ensure

  • React router动态加载组件之适配器模式的应用详解

    前言 本文讲述怎么实现动态加载组件,并借此阐述适配器模式. 一.普通路由例子 import Center from 'page/center'; import Data from 'page/data'; function App(){ return ( <Router> <Switch> <Route exact path="/" render={() => (<Redirect to="/center" />)}

  • vue2.* element tabs tab-pane 动态加载组件操作

    一.重要部分 1. 注意 <component :is=item.content></component> :表明模板 <el-tab-pane v-for="(item) in editableTabs" :key="item.name" :label="item.title" :name="item.name" > <component :is=item.content>&l

  • Angular.js实现动态加载组件详解

    前言 有时候需要根据URL来渲染不同组件,我所指的是在同一个URL地址中根据参数的变化显示不同的组件:这是利用Angular动态加载组件完成的,同时也会设法让这部分动态组件也支持AOT. 动态加载组件 下面以一个Step组件为示例,完成一个3个步骤的示例展示,并且可以通过URL user?step=step-one 的变化显示第N个步骤的内容. 1.resolveComponentFactory 首先,还是需要先创建动态加载组件模块. import { Component, Input, Vie

  • C#动态加载组件后如何在开发环境中调试详解

    动态加载组件 那就是简单的Assembly.Load动态加载dll而以.这网上资料也有不少.基本的思路基本上就是在本地上一个指定目录如[plugs]存在着一堆dll文件.主程序在初始运行时一般会把指定目录下的dll一次性用Assembly.Load加载进来.只要把指定目录变成从网络加载,或者加载指定目录前先检查网络上的是否有新版本.这就简单做成个最简单版本的热更新. 多数网上的资料就是然后就没有然后了.很多人就发现产品是通过动态加载组件了.但开发人员根本无法调试啊.不能调试就意味着开发难度大啊.

  • Vue加载组件、动态加载组件的几种方式

    什么是组件: 组件是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.在较高层面上,组件是自定义的元素,Vue.js的编译器为它添加特殊功能.在有些情况下,组件也可以是原生HTML元素的形式,以is特性扩展. 下面一段简单的代码给大家介绍Vue加载组件的几种方式,具体代码如下所示: //正常加载 import index from '../pages/index.vue' import view from '../pages/view.vue' //懒加载 const i

  • vue组件(全局,局部,动态加载组件)

    说说Vue.js组件 什么是组件:组件是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.在较高层面上,组件是自定义的元素,Vue.js的编译器为它添加特殊功能.在有些情况下,组件也可以是原生HTML元素的形式,以is特性扩展. vue组件有两种,一种是全局组件,一种是局部组件.整个项目经常用到的用全局写法,用到比较少的专供特定页面用的使用局部组件. one----全局组件引入写法:在项目的main.js中: 第一种,在main.js直接写template:' 模版字符串

  • Angular使用动态加载组件方法实现Dialog的示例

    网上的文章和教程基本上写到组件加载完成就没了!没了?!而且都是只能存在一个dialog,想要打开另一个dialog必须先销毁当前打开的dialog,之后看过 material 的实现方式,怪自己太蠢看不懂源码,就只能用自己的方式来实现一个dialog组件了 Dialog组件的目标:可以同时存在多个Dialog,可销毁指定Dialog,销毁后html中无组件残留且提供回调 动态加载组件的实现方式有两种,angular4.0版本之前使用ComponentFactoryResolver来实现,4.0之

  • Vue3的setup在el-tab中动态加载组件的方法

    公司某项目需求在页面显示的组件是根据角色变化而变化的,在这个项目中我使用了elementplus的el-tabs来动态的显示这些组件,如下图所示 <template> <component style="margin-top:15px" v-for="item in pageList" :is="item.module_id"/> </template> 数据内容大概是这样的 在未使用setup语法糖时候我要引

  • vue如何动态加载组件详解

    目录 使用场景: 需要动态导入组件的页面 核心组件的代码: 使用场景: 总结 使用场景: 项目中需要我们根据不同的业务需求呈现不同的业务场景,如果业务类型简单还好,直接全部引入判断即可,但随着我们代码的沉积,项目将会变得很难维护,这时候我们可以使用动态引入组件的方式来避免这个问题,首先第一步实现就是,在vue中,我们如何动态引入组件? 话不多说,直接上干货 需要动态导入组件的页面 在这个页面引入我们的组件Test <template> <div> <Test :data=&q

  • React 首页加载慢问题性能优化案例详解

    学习了一段时间React,想真实的实践一下.于是便把我的个人博客网站进行了重构.花了大概一周多时间,网站倒是重构的比较成功,但是一上线啊,那个访问速度啊,是真心慢,慢到自己都不能忍受,那么小一个网站,没几篇文章,慢成那样,不能接受.我不是一个追求完美的人,但这样可不行.后面大概花了一点时间进行性能的研究.才发现慢是有原因的. React这类框架? 目前主流的前端框架React.Vue.Angular都是采用客户端渲染(服务端渲染暂时不在本文的考虑范围内).这当然极大的减轻了服务器的压力.相对的浏

随机推荐