ReactJS-异步动态组件加载

时间:2019-09-06 16:28:45

标签: reactjs

情况

我从cms接收到json,其中描述了需要在任何给定页面上显示的内容。这个项目有50多个组件,因此我不想在每个页面上都需要它们,而是希望根据需要选择它们。

问题

我怎么

  1. 确保所有组件都可以导入(我认为这需要一些webpack技巧)
  2. 将json的内容节点转换为jsx时,请确保所描述的任何组件都已呈现。

当前想法

我可以遍历原始jsx并收集给定页面的所有标签,然后尝试通过

加载每个标签
const name = iteration.tagName;
dynCmps[name] = someAsynchronousLoad(path + name);

然后在加载完成后调度redux事件,以启动页面的全新呈现。

关于将原始文本内容转换为React js,我正在使用ReactHtmlParser

到目前为止最好的资源

1 个答案:

答案 0 :(得分:0)

这让我难过了几天。在与同事讨论了一段时间之后,我们决定减少30-50个组件的工作量对于减轻预先加载所有组件的性能影响所需要的工作量。

可以使用延迟加载,但我决定不这样做,因为额外的10毫秒加载(如果那样)根本不会引起注意。

import SomeComponent from "./SomeComponent.js"

const spoofedComponents = {
    SomeComponent: <SomeComponent />
}

const replaceFunc = (attribs, children) => {
  const keys = Object.keys(spoofedComponents);
  for(var i in keys) {
    const key = keys[i];
    // lower case is important here because react converts everything to lower case during text-to-html conversion - only react components can be camel case whereas html is pascal case.
    if(attribs.name === key.toLowerCase()) { 
      return spoofedComponents[key];
    }
  }

  return <p>unknown component</p>
}

...

//inside render

const raw = "<SomeComponent><SomeComponent />"
// it's VERY important that you do NOT use self-closing tags otherwise your renders will be incomplete.
{parse(raw, {
    replace: replaceFunc
})}

就我而言,我导入了30多个组件并将其映射到我的spoofedComponents常量。这有点麻烦,但这是必要的,因为react需要了解有关给定情况的所有信息,以便虚拟dom可以执行应有的工作-节省显示性能。优点是,现在,非开发人员(编辑)可以使用所见即所得来构建布局,并使用开发人员制造的组件来显示布局。

干杯!

修改

我仍然坚持添加自定义的道具和孩子。

修改

基本道具正在配合

const spoofedComponents = {
  SomeComponent: (opts) => {
    let s = {};
    if(opts.attribs.style)
      s = JSON.parse(opts.attribs.style);
    if(opts.attribs.classname) {
      opts.attribs.className = opts.attribs.classname;
      delete opts.attribs.classname;
    }

    return <APIRequest {...opts.attribs} style={s}>{opts.children[0].data}</APIRequest>
  }
}

...

const replaceFunc = (opts) => {
  const keys = Object.keys(spoofedComponents);
  for(var i in keys) {
    const key = keys[i];
    if(opts.name === key.toLowerCase()) { 
      const cmp = spoofedComponents[key](opts);
      return cmp;
    }
  }

  return <p>unknown component</p>
}

现在要弄清楚如何动态添加子组件。

编辑

这已经足够好了,我将保持原样。这是更新后的replaceFunc

const replaceFunc = (obj) => {
  const keys = Object.keys(spoofedComponents);
  for(var i in keys) {
    const key = keys[i];
    if(obj.name === key.toLowerCase()) { 
      if(obj.attribs.style)
        obj.attribs.style = JSON.parse(obj.attribs.style);
      if(obj.attribs.classname) {
        obj.attribs.className = obj.attribs.classname;
        delete obj.attribs.classname;
      }

      return React.createElement(spoofedComponents[key], obj.attribs, obj.children[0].data)
    }
  }

  return obj; //<p>unknown component</p>
}