该项目为 EPM 扩展机制核心库
执行 npm install @epmkit/epm-extend-core
来引入该库。
执行 npm start
进行开发
public 目录下的文件并不是用来发布的,而是调试用的例子插件。
执行 npm run build
进行编译
在宿主环境中执行 npm install @epmkit/epm-extend-core
来引入该库。
与该库配套使用的 @epmkit/cra-template-epm-plugin
用来创建插件仓库。
引入方法如下所示:
import React, { useEffect, useState } from 'react';
import Extend from '@epmkit/epm-extend-core';
const ExtendContext = React.createContext('Extend');
// 在节点中
function App() {
const [ExtendInstance, setExtendInstance] = useState(new Extend());
useEffect(() => {
async function initExtend() {
cosnt config = await fetchPluginList(nodeCode); // 获取当前节点的插件插槽配置
ExtendInstance.init(config);
setExtendInstance(ExtendInstance);
}
initExtend();
return () => {
ExtendInstance.dispose();
};
}, []);
return (
<ExtendContext.Provider value={ExtendInstance.Slot}>
<ChildElement />
</ExtendContext.Provider>
);
}
// 在组件中
function ChildElement() {
const Slot = React.useContext(ExtendContext);
// 可针对单个插槽关闭 js 沙箱
return <Slot name='slot-name' sandbox={false} fn={{
fnAAA: () => {/* 事件回调 */},
fnBBB: () => {/* 事件回调 */}
}} data={{
dataAAA: '', // 传递数据
dataBBB: {}
}} />;
}
-
在节点的最外层执行
React.createContext('Extend')
创建扩展机制执行上下文 -
在节点中执行
new Extend(options)
创建 扩展机制实例 ExtendInstance扩展机制支持对一些配置进行自定义设置,具体可设置属性如下:
字段 含义 类型 默认值 defaultStyleUrl 默认样式CSS地址 string //design.yonyoucloud.com/static/tinper-next/release/tinper-next.css
windowScope 插件绑定到window对象上的属性 string epmPlugin
sandbox 是否开启js沙箱 boolean true
-
在适当的时机执行实例的
init
方法,并传入插件插槽配置。init
时传入的config
变量为当前节点的插件插槽配置项,需要符合特定的数据结构,以下为例子:config = { pluginList: [ { name: 'aSmallBtn', scriptEntry: 'http://localhost:3030/plugin-aSmallBtn.e76d9341.js', styleEntry: 'http://localhost:3030/plugin-aSmallBtn.ababa1e9.css', version: '1.3.0', sandbox: false, }, { name: 'aSelectExample', scriptEntry: 'http://localhost:3030/plugin-aSelectExample.e86c0e5e.js', styleEntry: 'http://localhost:3030/plugin-aSelectExample.5df6a4d9.css', chunks: ['http://localhost:3030/js/plugin-chunk.155.cb4c80ac.js'], version: '1.4.1', }, ], slotList: [ { name: 'slot-a', plugins: ['aSelectExample', 'aSmallBtn'], }, { name: 'slot-b', plugins: ['aSelectExample'], }, { name: 'slot-c', plugins: [{ name: 'aSelectExample', version: '1.4.1' }], }, ], };
各字段含义如下
字段 含义 类型 例子 是否必需 pluginList 当前节点的插件列表 Array<Plugin> - √ Plugin.name 插件名 string aSmallBtn √ Plugin.scriptEntry 插件脚本文件入口地址 string http://localhost:3030/plugin-aSmallBtn.e76d9341.js
√ Plugin.styleEntry 插件样式文件入口地址 string http://localhost:3030/plugin-aSmallBtn.ababa1e9.css
- Plugin.chunks 插件的分包 Array<URL> ['http://localhost:3030/js/plugin-chunk.155.cb4c80ac.js']
- Plugin.version 插件的版本 string 1.3.0 - Plugin.sandbox 是否开启沙箱,默认开启,可设置为 false 对单个插件关闭 boolean false - slotList 当前节点的插槽配置 Array<Slot> - √ Slot.name 插槽名 string slot-a √ Slot.plugins 当前插槽的插件列表 Array<string|Plugin> - √ -
将扩展机制实例的插槽
ExtendInstance.Slot
作为上下文的值传递给子组件 -
在子组件适当的位置使用
<Slot name='slot-name' />
注入插槽
EPM 扩展机制核心库是和插件配置来使用的,插槽的开发者使用核心库来配置插槽和传递的数据方法,插件开发者需要开发插件来注入应用。
插件开发者执行 npx create-react-app ${plugin-repo-name} --template @epmkit/cra-template-epm-plugin
来创建插件仓库,其中 ${plugin-repo-name}
为插件仓库的名称。
插件的开发同普通 React 组件开发方式相同,只不过组件的 props 是通过插槽传递过来的数据。
一个插件例子如下:
export default function SamllBtn({ fn, data, emit, on }) {
const { btnName, isBtnShow } = data;
const { hideBtn, showBtn } = fn;
useEffect(() => {
on('anotherPlugin:message', payload => {
console.log('receiveMessage', payload);
});
}, []);
const handleClick = useCallback(() => {
if (isBtnShow) {
hideBtn();
return;
}
showBtn();
emit('smallBtnClick', !isBtnShow);
}, [hideBtn, isBtnShow, showBtn]);
return (
<Button
className='plugin-btn'
style={{ width: 400 }}
onClick={handleClick}
type='primary'>{`${btnName}按钮`}</Button>
);
}
插件的 props 含义如下:
字段名 | 含义 | 例子 |
---|---|---|
fn | 由插槽定义的方法,通过执行方法改变页面状态 | - |
data | 由插槽传递的数据,获取当前插槽传递的实时数据 | - |
emit | 插件间通信方法,发送事件与数据 | emit('event', data) |
on | 插件间通信方法,监听其他插件发送的事件并对载荷做出处理 需要注意的是,监听时需要带上监听的插件名,插件名和事件之间以冒号 : 连接 |
on('pluginName:event', (payload) =>{}) |