您好,欢迎访问一九零五行业门户网

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

本篇文章给大家带来的内容是关于react和redux的动态导入(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
代码分离与动态导入
对于大型 web应用程序,代码组织非常重要。 它有助于创建高性能且易于理解的代码。 最简单的策略之一就是代码分离。 使用像 webpack 这样的工具,可以将代码拆分成更小的部分,它们分为两个不同的策略,静态和动态。
通过静态代码分离,首先将应用程序的每个不同部分作为给定的入口点。 这允许 webpack 在构建时将每个入口点拆分为单独的包。 如果我们知道我们的应用程序的哪些部分将被浏览最多,这是完美的。
动态导入使用的是 webpack 的 import 方法来加载代码。由于 import 方法返回一个 promise,所以可以使用async wait 来处理返回结果。
// getcomponent.jsasync 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.jsimport * as react from 'react'export default {    view: () => <p>my modules view</p>}
现在我们使用导入方法来加载这个文件,我们可以很容易地访问模块的 view  组件,例如
async function getcomponent() {    const {default} = await import('./my-module')    return react.createelement(default.view)})
然而,我们仍然没有使用 react 中的方法来延迟加载模块。通过创建一个 lazyloadmodule 组件来实现这一点。该组件将负责解析和渲染给定模块的视图组件。
// lazymodule.jsimport * 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 <p>loading module...</p>;    if (module.view) return react.createelement(module.view);  }}
以下是使用 lazyloadmodule 组件来加载模块的视图方式:
// my-app.jsimport {lazyloadmodule} from './lazyloadmodule'const myapp = () => (    <p classname='app'>        <h1>hello</h1>        <lazyloadmodule resolve={() => import('./modules/my-module')} />    </p>)reactdom.render(<myapp />, document.getelementbyid('root'))
下面是一个线上的示例,其中补充一些异常的处理。
https://codesandbox.io/embed/...
通过使用 react 来处理每个模块的加载,我们可以在应用程序的任何时间延迟加载组件,这包括嵌套模块。
使用 redux
到目前为止,我们已经演示了如何动态加载应用程序的模块。然而,我们仍然需要在加载时将正确的数据输入到我们的模块中。
让我们来看看如何将 redux 存储连接到模块。 我们已经通过公开每个模块的视图组件为每个模块创建了一个 api。 我们可以通过暴露每个模块的 reducer 来扩展它。 还需要公开一个名称,在该名称下我们的模块状态将存在于应用程序的store 中。
// my-module.jsimport * as react from 'react'import {connect} from 'react-redux'const mapstatetoprops = (state) => ({    foo: state['my-module'].foo,})const view = connect(mapstatetoprops)(({foo}) => <p>{foo}</p>)const fooreducer = (state = 'some stuff') => {    return state}const reducers = {    'foo': fooreducer,}export default {    name: 'my-module',    view,    reducers,}
上面的例子演示了我们的模块如何获得它需要渲染的状态。
但是我们需要先对我们的 store  做更多的工作。我们需要能够在模块加载时注册模块的 reducer。因此,当我们的模块 dispatche 一个 action 时,我们的 store 就会更新。我们可以使用 replacereducer 方法来实现这一点。
首先,我们需要添加两个额外的方法,registerdynamicmodule 和 unregisterdynamicmodule 到我们的 store 中。
// store.jsimport * as redux form 'redux'const { createstore,  combinereducers } = redux// export our createstore functionexport 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 = () => (    <provider store={store}>        ...    </provider>)
接下来,需要更新 lazyloadmodule ,以便它可以在我们的 store 中注册 reducer 模块。
我们可以通过 props 获取 store。这很简单,但这意味着我们每次都必须检索我们的 store,这可能会导致 bug。记住这一点,让 lazyloadmodule 组件为我们获取 store。
当 react-redux <provider /> 组件将 store 添加到上下文中时,只需要使用 contexttypes 在lazyloadmodule 中获取它。
// 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.jsexport default {    name: 'my-module',    view,    reducers,}
更新 lazyloadmodule 的 componentdidmount和 componentwillunmount 方法来注册和注销每个模块:
// 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将按需加载。此外,我们还减少了包的大小和加载时间,这意味着每个模块都可以看作是一个单独的应用程序。
本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注的javascript视频教程栏目!
以上就是react和redux的动态导入(附代码)的详细内容。
其它类似信息

推荐信息