这篇文章主要介绍了React远程动态组件怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇React远程动态组件怎么实现文章都会有所收获,下面我们一起来看看吧。
远程动态组件实现
远程动态组件库
远程动态组件库项目结构如下所示:
. ├── babel.config.js ├── package.json ├── rollup.config.js └── src ├── Button.js ├── Text.js
我们简单实现了两个组件 Button
和 Text
:
import React from 'react' export default ({children}) => { return <button style={{color: 'blue'}}>{children}</button> }
import React from 'react' export default ({children}) => { return <span style={{color: 'blue'}}>{children}</span> }
我们使用 rollup 对其进行打包,之所以用 rollup 是因为其打包出来的代码非常简洁,方便我们查看,rollup 配置为:
import babel from 'rollup-plugin-babel' import fs from 'fs' const components = fs.readdirSync('./src') export default components.map((filename) => { return { input: `./src/${filename}`, output: { file: `dist/${filename}`, format: 'cjs', }, plugins: [babel()], } })
打包后的结果如下所示:
. ├── dist │ └── Button.js │ └── Text.js
其中 Button.js
如下所示:
'use strict' var React = require('react') function _interopDefaultLegacy(e) { return e && typeof e === 'object' && 'default' in e ? e : {default: e} } var React__default = /*#__PURE__*/ _interopDefaultLegacy(React) var Button = function (_ref) { var children = _ref.children return /*#__PURE__*/ React__default['default'].createElement( 'button', { style: { color: 'blue', }, }, children ) } module.exports = Button
然后我们使用 http-server 在 dist
目录下开启一个静态文件服务,则可以通过 http://localhost:8080/Button.js
获取到打包后的代码。
远程组件库介绍完毕,接下来介绍业务项目中如何使用。
接入远程组件库
我们使用 create-react-app
创建一个 React 应用,并新增一个 DynamicComponent
组件:
const DynamicComponent = ({name, children, ...props}) => { const Component = useMemo(() => { return React.lazy(async () => fetchComponent(name)) }, [name]) return ( <Suspense fallback={ <div style={{alignItems: 'center', justifyContent: 'center', flex: 1}}> <span style={{fontSize: 50}}>Loading...</span> </div> }> <Component {...props}>{children}</Component> </Suspense> ) } export default React.memo(DynamicComponent)
这里使用到了 React 中的 Suspense
组件和 React.lazy
方法,关于他们的用法这里不做过多解释,整个 DynamicComponent
组件的含义是远程加载目标组件,这个过程该组件会渲染传入 Suspense
参数 fallback
之中的内容,最后会使用加载成功的组件进行替换。接下来看看 fetchComponent
是如何实现的:
const fetchComponent = async (name) => { const text = await fetch( `http://127.0.0.1:8080/${name}.js?ts=${Date.now()}` ).then((a) => { if (!a.ok) { throw new Error('Network response was not ok') } return a.text() }) const module = getParsedModule(text, name) return {default: module.exports} }
该方法会发起网络请求得到组件的代码,并交给 getParsedModule
去解析,最后得到模块返回。我们来看一下 getParsedModule
是怎么实现的:
const packages = { react: React, } const getParsedModule = (code) => { let module = { exports: {}, } const require = (name) => { return packages[name] } Function('require, exports, module', code)(require, module.exports, module) return module }
这里使用 Function
来运行传入的代码,因为打包远程组件的时候并没有将 react
库打包进去,所以这里需要实现 require
这个方法。
我们结合之前打包得到的 Button.js
来看这段代码,它其实同下面这个代码是等价的:
const packages = { react: React, } const getParsedModule = (code, moduleName) => { let module = { exports: {}, } const require = (name) => { return packages[name] } ;((require, exports, module) => { 'use strict' var React = require('react') function _interopDefaultLegacy(e) { return e && typeof e === 'object' && 'default' in e ? e : {default: e} } var React__default = /*#__PURE__*/ _interopDefaultLegacy(React) var Button = function (_ref) { var children = _ref.children return /*#__PURE__*/ React__default['default'].createElement( 'button', { style: { color: 'blue', }, }, children ) } module.exports = Button })(require, module.exports, module) return module }
最后我们可以按照如下方式来使用 DynamicComponent
组件:
import DynamicComponent from './DynamicComponent' function App() { return ( <div> <DynamicComponent name='Button'>Click Me</DynamicComponent> <DynamicComponent name='Text'>Remote Component</DynamicComponent> </div> ) } export default App
现在我们尝试修改远程动态组件库中的组件,重新打包后就可以马上看到修改后的效果了。
关于“React远程动态组件怎么实现”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“React远程动态组件怎么实现”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注云搜网行业资讯频道。