热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

React和Redux的动态导入(附代码)

本篇文章给大家带来的内容是关于React和Redux的动态导入(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

本篇文章给大家带来的内容是关于React和Redux的动态导入(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

代码分离与动态导入

对于大型 Web应用程序,代码组织非常重要。 它有助于创建高性能且易于理解的代码。 最简单的策略之一就是代码分离。 使用像 Webpack 这样的工具,可以将代码拆分成更小的部分,它们分为两个不同的策略,静态和动态。

通过静态代码分离,首先将应用程序的每个不同部分作为给定的入口点。 这允许 Webpack 在构建时将每个入口点拆分为单独的包。 如果我们知道我们的应用程序的哪些部分将被浏览最多,这是完美的。

动态导入使用的是 Webpack 的 import 方法来加载代码。由于 import 方法返回一个 promise,所以可以使用async wait 来处理返回结果。

// getComponent.js
async function getComponent() {
   const {default: module} = await import('../some-other-file')
   const element = document.createElement('p')
   element.innerHTML = module.render()
   return element
}

虽然这是一个很不自然的例子,但是可以看到这是一个多么简单的方法。通过使用 Webpack 来完成繁重的工作,我们可以将应用程序分成不同的模块。当用户点击应用程序的特定部分时,才加载我们需要的代码。

如果我们将这种方法与 React 提供给我们的控制结构相结合,我们就可以通过延迟加载来进行代码分割。这允许我们将代码的加载延迟到最后一分钟,从而减少初始页面加载。

使用 React 处理延迟加载

为了导入我们的模块,我们需要决定应该使用什么 API。考虑到我们使用 React 来渲染内容,让我们从这里开始。

下面是一个使用 view 命名空间导出模块组件的简单API。

// my-module.js
import * as React from 'react'

export default {
    view: () => 

My Modules View

}

现在我们使用导入方法来加载这个文件,我们可以很容易地访问模块的 view 组件,例如

async function getComponent() {
    const {default} = await import('./my-module')
    return React.createElement(default.view)
})

然而,我们仍然没有使用 React 中的方法来延迟加载模块。通过创建一个 LazyLoadModule 组件来实现这一点。该组件将负责解析和渲染给定模块的视图组件。

// lazyModule.js
import * as React from "react";

export class LazyLoadModule extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      module: null
    };
  }
 
  // after the initial render, wait for module to load
  async componentDidMount() {
    const { resolve } = this.props;
    const { default: module } = await resolve();
    this.setState({ module });
  }

  render() {
    const { module } = this.state;

    if (!module) return 

Loading module...

; if (module.view) return React.createElement(module.view); } }

以下是使用 LazyLoadModule 组件来加载模块的视图方式:

// my-app.js

import {LazyLoadModule} from './LazyLoadModule'

const MyApp = () => (
    

Hello

import('./modules/my-module')} />

) ReactDOM.render(, document.getElementById('root'))

下面是一个线上的示例,其中补充一些异常的处理。

https://codesandbox.io/embed/...

通过使用 React 来处理每个模块的加载,我们可以在应用程序的任何时间延迟加载组件,这包括嵌套模块。

使用 Redux

到目前为止,我们已经演示了如何动态加载应用程序的模块。然而,我们仍然需要在加载时将正确的数据输入到我们的模块中。

让我们来看看如何将 redux 存储连接到模块。 我们已经通过公开每个模块的视图组件为每个模块创建了一个 API。 我们可以通过暴露每个模块的 reducer 来扩展它。 还需要公开一个名称,在该名称下我们的模块状态将存在于应用程序的store 中。

// my-module.js
import * as React from 'react'
import {connect} from 'react-redux'

const mapStateToProps = (state) => ({
    foo: state['my-module'].foo,
})
const view = connect(mapStateToProps)(({foo}) => 

{foo}

) const fooReducer = (state = 'Some Stuff') => { return state } const reducers = { 'foo': fooReducer, } export default { name: 'my-module', view, reducers, }

上面的例子演示了我们的模块如何获得它需要渲染的状态。

但是我们需要先对我们的 store 做更多的工作。我们需要能够在模块加载时注册模块的 reducer。因此,当我们的模块 dispatche 一个 action 时,我们的 store 就会更新。我们可以使用 replaceReducer 方法来实现这一点。

首先,我们需要添加两个额外的方法,registerDynamicModuleunregisterDynamicModule 到我们的 store 中。

// store.js
import * as redux form 'redux'

const { createStore,  combineReducers } = redux

// export our createStore function
export default reducerMap => {
    
    const injectAsyncReducers = (store, name, reducers) => {
        // add our new reducers under the name we provide
        store.asyncReducers[name] = combineReducers(reducers);
        // replace all of the reducers in the store, including our new ones
        store.replaceReducer(
            combineReducers({
                ...reducerMap,
                ...store.asyncReducers
            })
        );
    };
    
    // create the initial store using the initial reducers that passed in
    const store = createStore(combineReducers(reducerMap));
    // create a namespace that will later be filled with new reducers
    store.asyncReducers = {};
    // add the method that will allow us to add new reducers under a given namespace
    store.registerDynamicModule = ({ name, reducers }) => {
        console.info(`Registering module reducers for ${name}`);
        injectAsyncReducers(store, name, reducers);
    };
    // add a method to unhook our reducers. This stops our reducer state from updating any more.
    store.unRegisterDynamicModule = name => {
        console.info(`Unregistering module reducers for ${name}`);
        const noopReducer = (state = {}) => state;
        injectAsyncReducers(store, name, noopReducer);
    };
    
    // return our augmented store object
    return store;
}

如你所见,代码本身非常简单。 我们将两种新方法添加到我们的 store 中。 然后,这些方法中的每一种都完全取代了我们 store 中的 reducer

以下是如何创建扩充 store

import createStore from './store'

const rootReducer = {
    foo: fooReducer
}

const store = createStore(rootReducer)

const App = () => (
    
        ...
    
)

接下来,需要更新 LazyLoadModule ,以便它可以在我们的 store 中注册 reducer 模块。

我们可以通过 props 获取 store。这很简单,但这意味着我们每次都必须检索我们的 store,这可能会导致 bug。记住这一点,让 LazyLoadModule 组件为我们获取 store

react-redux 组件将 store 添加到上下文中时,只需要使用 contextTypesLazyLoadModule 中获取它。

// lazyModule.js 
export class LazyLoadModule extends React.component {
    ...
    async componentDidMount() {
        ...
        const {store} = this.context
    }
}

LazyLoadModule.cOntextTypes= {
    store: PropTypes.object,
}

现在可以从 LazyLoadModule 的任何实例访问我们的 store。 剩下的唯一部分就是把 reducer 注册到 store 中。 记住,我们是这样导出每个模块:

// my-module.js
export default {
    name: 'my-module',
    view,
    reducers,
}

更新 LazyLoadModulecomponentDidMountcomponentWillUnmount 方法来注册和注销每个模块:

// lazyModule.js 
export class LazyLoadModule extends React.component {
    ...
    async componentDidMount() {
        ...
        const { resolve } = this.props;
        const { default: module } = await resolve();
        const { name, reducers } = module;
        const { store } = this.context;
        if (name && store && reducers)
            store.registerDynamicModule({ name, reducers });
         this.setState({ module });
    }
    ...
    
    componentWillUnmount() {
        const { module } = this.state;
        const { store } = this.context;
        const { name } = module;
        if (store && name) store.unRegisterDynamicModule(name);
    }
}

线上示例如下:
https://codesandbox.io/s/znx1...

总结:

通过使用 Webpack 的动态导入,我们可以将代码分离添加到我们的应用程序中。这意味着我们的应用程序的每个部分都可以注册自己的 components 和 reducers,这些 components 和 reducers将按需加载。此外,我们还减少了包的大小和加载时间,这意味着每个模块都可以看作是一个单独的应用程序。

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的Javascript视频教程栏目!

以上就是React和Redux的动态导入(附代码)的详细内容,更多请关注 第一PHP社区 其它相关文章!


推荐阅读
  • Itwasworkingcorrectly,butyesterdayitstartedgiving401.IhavetriedwithGooglecontactsAPI ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 大连微软技术社区举办《.net core始于足下》活动,获得微软赛百味和易迪斯的赞助
    九月十五日,大连微软技术社区举办了《.net core始于足下》活动,共有51人报名参加,实际到场人数为43人,还有一位专程从北京赶来的同学。活动得到了微软赛百味和易迪斯的赞助,场地也由易迪斯提供。活动中大家积极交流,取得了非常成功的效果。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 禁止程序接收鼠标事件的工具_VNC Viewer for Mac(远程桌面工具)免费版
    VNCViewerforMac是一款运行在Mac平台上的远程桌面工具,vncviewermac版可以帮助您使用Mac的键盘和鼠标来控制远程计算机,操作简 ... [详细]
  • 表单提交前的最后验证:通常在表单提交前,我们必须确认用户是否都把必须填选的做了,如果没有,就不能被提交到服务器,这里我们用到表单的formname.submit()看演示,其实这个对于我们修炼道 ... [详细]
  • 用JavaScript实现的太空人手表
    用JavaScript实现的太空人手表-JS写的太空人手表,没有用canvas、svg。主要用几个大的函数来动态显示时间、天气这些。天气的获取用到了AJAX请求。代码中有详细的注释 ... [详细]
  • Iwouldliketobeabletohaveasidebarthatcanbetoggledinandoutonabuttonpress.However ... [详细]
  • 但有时候,需要当某事件触发时,我们先做一些操作,然后再跳转,这时,就要用JAVASCRIPT来实现这一跳转功能。下面是具体的做法:一:跳转到新页面,并且是在新窗口中打开时:复制代码代码如下:fu ... [详细]
  • JavaScript在常人看来都是门出不了厅堂的小语言,仅管它没有明星语言的闪耀,但至少网页的闪耀还是需要它的,同时它是一门很实用的语言,本人平时就喜欢拿它来写点实用工具或应用,本文演示用JavaSc ... [详细]
author-avatar
pop6959140
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有