update readme

This commit is contained in:
yehuozhili
2022-04-24 23:07:41 +08:00
parent a04aaf2b61
commit 65fe8d8538
10 changed files with 60 additions and 990 deletions

View File

@@ -155,6 +155,4 @@ MIT
## Todo
重构弹窗
重构事件
完善文档

View File

@@ -38,7 +38,7 @@ Add color and style settings for markline
## 0.11.9
A new setting panel is added to control adsorption scaling and other behaviors.
Fixed pop-up button style issues.
The repair prompt is not displayed.
Fix the problem that some prompts do not display.
## 0.11.8
Timeline adds auto focus function.
## 0.11.7
@@ -53,7 +53,7 @@ Change the position of rotation justification
Fix guide line bug
Optimized drag and drop algorithm
## 0.11.3
Increase the function of rotary return.
Positive rotation function is added.
Optimize mouse style.
## 0.11.2
Optimize drag speed
@@ -103,7 +103,7 @@ Add animation component timeline. You can preview all animations better.
The animation part is reconstructed, which can support the simultaneous configuration of multiple animations.
The minimum value of canvas drag is changed to 0.
## 0.7.7
Optimize the drag logic of the canvas to move more smoothly.
Drag and drop to make the canvas smoother and move logically.
## 0.7.6
The custom rightglobalcustom type on the right is changed to the function passed in config
## 0.7.5

View File

@@ -8,18 +8,18 @@ nav:
## The chart is constantly refreshed as it moves
Please use fast deep equal to compare the required data. If they are the same, ignore the update.
## Unable to select components or preview adaptation issues
The absolute positioning component must have an initial width and height. Although the width and height will be added to the component during dragging, if the user does not drag at the beginning, the component has no width and height, which will not only affect the selection judgment, but also affect the calculation of the final preview.
## The functions dynamically registered by the component are always retained
The absolute positioning component must have the initial width and height. Although the width and height will be added to the component during dragging, if the user does not drag at the beginning, the component has no width and height, which will not only affect the selection judgment, but also affect the calculation of the final preview.
## The functions dynamically registered by components will always be retained
The component function needs to call the unloading method when the component is unloaded, otherwise it will always exist.
## Form verification submission ideas
There are many ways to verify and submit forms, because all the data is connected, or you can write a form component directly.
When the form component is not used, the simple way is to make a verification function and submission function for each input component.
In this way, whether to verify depends on the user's selection, and the thrown input allows the user to choose where to put it, and the user names the variable.
When clicking the submit button, call the verification function and submission function of all components to throw them to the context, then aggregate them into objects through the context aggregation function, and finally send them to the corresponding back end through the sending function, so as to complete the whole process. You can try this demo in example.
If the operator can understand the interface documents provided by the back-end, the operator can spell out the fields desired by the back-end through naming.
If the operator can understand the interface documents provided by the back-end, he can spell out the desired fields of the back-end through naming.
If you don't need documentation, some values can also be written dead at development time.
Another way is to write a submit button specifically, fix the parameters and some rules, such as stipulating that all forms in the page will be collected and submitted.
Then we can use the data source to automatically submit all form output contents to the data source. The last submit button extracts the key in the format specified by the data source and sends it to the back end.
Then we can use the data source to automatically submit all the form output content to the data source. The last submit button extracts the key in the format specified by the data source and sends it to the back end.
## Top to bottom problem
A small partner responded that the operation of placing the top and bottom is a little unreasonable. In fact, zindex should not be used to make the top and bottom, which is inconsistent with the order of layers, and there will be problems when using zindex to set the bottom, because the element zindex cannot be lower than the canvas, so it is common sense to raise the order.
## Multilingual removal

View File

@@ -6,28 +6,28 @@
### store
Store is similar to the concept of redux. It internally implements the functions of redo, undo, publish and subscribe, replace data, forced refresh and so on.
Store can be obtained in config.
At the beginning, usestorestate and react need to be combined. At this time, store.forceupdate can be used at any position, or state can be used to obtain the data in the store.
The most important function of the store is to save the JSON queue for each modification.
At the beginning, it is necessary to combine usestorestate with react. At this time, store can be used anywhere Forceupdate can also use state to obtain the data in the store.
The most important function of JSON is to save the queue every time.
If you need to update the data, use the SetData method to update after the deep copy.
If you don't leave a record on redo or undo when you need to update, please operate the queue to delete the saved content.
If you don't leave records on redo or undo when you need to update, please operate the queue to delete the saved contents.
If you want to see the view update after changing the data, you can use forceupdate.
### Events
The events of dooringx lib are on the eventcenter, which integrates the function center and an event chain.
The event of dooringx lib is on the eventcenter, which integrates the function center and an event chain.
You can get the time of component registration in the event center. Timing is similar to the component life cycle. It can be called at the corresponding timing after registration.
The functions in the function center will be combined with the timing, and then the event chain will uniformly process the queue set by the user.
Each event chain will have a context object during execution, which will run through the event chain.
### Command
The commands of dooringx lib are managed by the commander.
Redo and undo commands are provided internally by default. You can add a commander through a plug-in.
The commander integrates shortcut key configuration internally, and uses the keys of keyboard events for registration. If Ctrl, ALT and meta keys are used, the corresponding plus sign can be added for key combination registration, and the case is ignored internally (note! The case of the registered key name is not ignored, but the keys of a and a are equivalent in processing).
The commander integrates shortcut key configuration internally, and uses the keys of keyboard events for registration. If Ctrl, ALT and meta keys are used, the corresponding plus sign can be added for key combination registration, and the case is ignored internally (note! The case of the registered key name is not ignored, but the key processing of a and a is equivalent).
### Pop up window
Dooringx lib has a built-in pop-up system, which is converted through storechanger.
Dooringx lib has a built-in pop-up system, which is converted through store.
Therefore, when making some scenes, you may need to consider whether to edit them in pop-up window.
Each pop-up window only saves the data in the block, while data such as events will only exist in the master data.
After the pop-up window is saved, the pop-up window data will be replaced in the main data memory and replaced again when editing.
You can use the methods on storechanger to judge, or directly obtain the data source data. See API for details.
You can use the method on the store to judge, or directly obtain the data source data. See API for details.
### Data source
The data source of dooringx lib is not the same thing as the store mentioned above.
It is located in the datacenter. The original intention of designing data source is to make people who do not understand the code better understand.
It is located in the datacenter. The original intention of designing data source is to make people who don't understand the code better understand.
The operation of events can be completely separated from the data source, as long as the user knows how to fill in parameters.
Therefore, during event configuration, multiple options can be used to obtain data from the data source and convert it into parameters.

View File

@@ -44,7 +44,7 @@ commander内部集成了快捷键配置使用键盘事件的key进行注册
### 弹窗
dooringx-lib内置弹窗系统弹窗系统是通过storeChanger进行转换而成。
dooringx-lib内置弹窗系统弹窗系统是通过store进行转换而成。
所以在某些情景制作时,可能需要考虑是否在弹窗编辑下的情况。
@@ -52,7 +52,7 @@ dooringx-lib内置弹窗系统弹窗系统是通过storeChanger进行转换
在弹窗保存后,弹窗数据会被置换于主数据内存着,需要编辑时重新置换出来。
可以使用storeChanger上的方法进行判断或者直接获取数据源数据等具体见API。
可以使用store上的方法进行判断或者直接获取数据源数据等具体见API。
### 数据源

View File

@@ -4,67 +4,23 @@
order: 3
---
### Plug in import
The dooringx lib plug-in requires an object of type 'partial < initconfig >'.
The dooringx lib plug-in requires an object of type 'partial<initconfig>'.
For multiple plug-ins, you need to use the 'userconfigmerge' exported by dooringx lib to merge.
Not all properties of userconfigmerge will be merged, and some properties will be overwritten.
```
* 部分无法合并属性如果b传了会以b为准
* initstore不合并
* leftallregistmap合并
* leftRenderListCategory合并
* rightRenderListCategory合并
* rightGlobalCustom 不合并
* initComponentCache合并
* initFunctionMap合并
* initDataCenterMap合并
* initCommandModule合并
* initFormComponents合并
```
Config supports partial configuration of asynchronous import, such as classification on the left. This is an experimental function, so it is not recommended.
### Left panel
On the left panel, enter leftrenderlistcategory.
```js
leftRenderListCategory: [
{
type: 'basic',
icon: <HighlightOutlined />,
displayName: '基础组件',
},
{
type: 'xxc',
icon: <ContainerOutlined />,
custom: true,
customRender: <div>我是自定义渲染</div>,
},
],
```
Type is the category. The category displayed by the component on the left is determined by this field.
Icon is a small icon on the left.
On the left is the small icon.
When custom is true, you can use customrender to customize the rendering.
### Left side assembly
To be updated
### Plug in import
The left component is placed in the leftregistmap of the object.
The left component should be placed in the leftregistmap of the object.
The left component supports synchronous import or asynchronous import.
```js
const LeftRegistMap: LeftRegistComponentMapItem[] = [
{
type: 'basic',
component: 'button',
img: 'icon-anniu',
displayName: '按钮',
urlFn: () => import('./registComponents/button'),
},
];
```
If you need to import components asynchronously, you need to fill in urlfn and a function that returns promise. Remote loading of components can also be supported, as long as webpack is equipped with it.
If you need to import components synchronously, you need to put the components into the initcomponentcache of the configuration item, so that they will be registered in the componentregister when loaded.
```js
initComponentCache: {
modalMask: { component: MmodalMask },
},
```
### Component writing
Component needs to export an object generated by componentitemfactory.
The component needs to export an object generated by componentitemfactory.
```js
const MButton = new ComponentItemFactory(
'button',
@@ -94,15 +50,15 @@ export default MButton;
```
The first parameter is the component registration name, and the second parameter is used to display the usage.
The third parameter is used to configure the configuration item component of the right panel. The key is the classification of the right panel, and the value is the configuration item component array.
The fourth parameter will configure the initial value of the component. In particular, the manufacturing component must have the initial width and height (not supported by the content), otherwise there will be a problem when selecting all during adaptation.
There are many useful properties in this initial value. For example, fixed represents fixed positioning. You can change this value in combination with configuration items so that components can be fixed positioning.
Also, candrag is similar to the lock command. Locked elements cannot be dragged.
The fourth parameter will configure the initial value of the component. In particular, the manufacturing component must have the initial width and height (not supported by the content), otherwise there will be problems when selecting all during adaptation.
There are many useful properties in this initial value. For example, fixed represents fixed positioning. You can change this value in combination with configuration items to make the component fixed positioning.
And candrag is similar to the lock command. Locked elements cannot be dragged.
The rotate in the initial value needs an object. Value represents the rotation angle and canrotate represents whether the rotation can be operated. (supported from version 0.7.0)
The fifth parameter is a function. You will get the configuration from the receive attribute in the configuration item (the default configuration is receive for the time being). For example, if the received in the above example is text, the field will be received in the data in the function.
Context generally has only preview and edit for environment judgment.
Context generally has only preview and edit, which are used to judge the environment.
Config can get all the data for use when making events.
The sixth parameter resize is used to determine whether scaling can be performed. When it is false, scaling cannot be performed.
The seventh parameter is needposition. After some components are moved into the canvas, the drop point will be adopted by default. This configuration item is true by default, that is, the position to be dragged. When it is false, the component's top and left positioning will be used to place it.
The sixth parameter resize is to judge whether scaling can be performed. When it is false, scaling cannot be performed.
The seventh parameter is needposition. After some components are moved into the canvas, the drop point will be adopted by default. This configuration item is true by default, which is the position to be dragged. When it is false, the top and left positioning of the components will be used to place them.
### Event registration
#### Timing registration
As mentioned earlier, events have timing and functions, so hook can be used to register timing in the component:
@@ -123,55 +79,12 @@ yehuozhili
```
The first parameter is the registered time name, and the second parameter is the last parameter config in the render function
#### Function registration
Functions are thrown by components and can be loaded into the event chain. For example, if I register a function to change the text, I can call the function at the time of any component, so as to trigger the component to change the text.
The function registration needs to be put into useeffect, and the function needs to be unloaded when the component is unloaded! Otherwise, there will be more and more functions.
Note that the component ID should be taken with the component ID, because a component can drag n components to generate n functions.
```js
useEffect(() => {
const functionCenter = eventCenter.getFunctionCenter();
const unregist = functionCenter.register(
`${pr.data.id}+改变文本函数`,
async (ctx, next, config, args, _eventList, iname) => {
const userSelect = iname.data;
const ctxVal = changeUserValue(
userSelect['改变文本数据源'],
args,
'_changeval',
config,
ctx
);
const text = ctxVal[0];
setText(text);
next();
},
[
{
name: '改变文本数据源',
data: ['ctx', 'input', 'dataSource'],
options: {
receive: '_changeval',
multi: false,
},
},
],
`${pr.data.id}+改变文本函数`
);
return () => {
unregist();
};
}, []);
```
The function is thrown by the component and can be loaded into the event chain. For example, if I register a function to change the text, I can call the function at the time of any component, so as to trigger the component to change the text.
Function registration needs to be put into useeffect. At present, there is no need to uninstall actively, but when communicating with the function on the pop-up window, you may need to uninstall in the preview environment, otherwise the second execution may not take effect.
Note that the ID should be accompanied by the component ID, because a component can drag n components to generate n functions.
See later function development for parameters and configuration in the function.
### Right side panel
The configuration of the right panel is the same as that of the left panel:
```js
export interface RightMapRenderListPropsItemCategory {
type: string;
icon: ReactNode;
custom?: boolean;
customRender?: (type: string, current: IBlockType) => ReactNode;
}
```
Type will affect the key name of the third parameter of the left component during development. The key name represents the type displayed on the right.
Icon can put text or icons for panel switching.
If custom is true, the display under this panel can be customized through customrender.
@@ -182,7 +95,7 @@ When importing, just match the developed components into an object and put it in
initFormComponents: Formmodules,
```
#### Right side component development
First, for a good development experience, you need to define a formmap type:
First, in order to have a good development experience, you need to define a formmap type:
```js
export interface FormBaseType {
receive?: string;
@@ -208,7 +121,7 @@ current: IBlockType;
config: UserConfig;
}
```
That is, where data is the formmap type and current is the currently clicked component, needless to say config.
That is, where data is of formmap type and current is the currently clicked component, needless to say config.
Remember the third parameter in component development on the left? So it's all related:
```js
style: [
@@ -218,7 +131,7 @@ label: '文字',
}),
],
```
The generics of the createpanneloptions function are filled with the corresponding components, which will give a good prompt to the received configuration items.
The generics of the createpaneloptions function are filled with the corresponding components, which will give a good prompt to the received configuration items.
All you need to do in the configuration item component is to receive the configuration item from the component, and then modify the property of current:
```js
function MInput(props: MInputProps) {
@@ -251,7 +164,7 @@ store.setData({ ...clonedata, block: [...newblock] });
}
```
Because you can easily get the store, you can modify the data anywhere.
Associate the value of the component with the property of current, and onchange to modify the store, thus completing a two-way binding.
Associate the value of the component with the attribute of current, and onchange to modify the store, so as to complete a two-way binding.
Note: if your right component needs attributes other than block, you may need to judge whether it is in pop-up mode.
####Import of commands
The command object can be imported into the initcommandmodule of the plug-in
@@ -259,211 +172,45 @@ The command object can be imported into the initcommandmodule of the plug-in
initCommandModule: commandModules,
```
#### Command development
The command needs to export an object generated by commanderitemfactory.
A commandfactory object needs to be exported.
```js
import { CommanderItemFactory } from 'dooringx-lib';
const undo = new CommanderItemFactory(
'redo',
'Control+Shift+z',
(store) => {
store.redo();
store. redo();
},
'redo '
);
export default undo;
```
The first parameter is the registration name.
The second parameter is the shortcut key name, and the shortcut key mapping is the key value of the keyboard event:
```js
Cancel: 3,
Help: 6,
Backspace: 8,
Tab: 9,
Clear: 12,
Enter: 13,
Shift: 16,
Control: 17,
Alt: 18,
Pause: 19,
CapsLock: 20,
Escape: 27,
Convert: 28,
NonConvert: 29,
Accept: 30,
ModeChange: 31,
' ': 32,
PageUp: 33,
PageDown: 34,
End: 35,
Home: 36,
ArrowLeft: 37,
ArrowUp: 38,
ArrowRight: 39,
ArrowDown: 40,
Select: 41,
Print: 42,
Execute: 43,
PrintScreen: 44,
Insert: 45,
Delete: 46,
0: 48,
')': 48,
1: 49,
'!': 49,
2: 50,
'@': 50,
3: 51,
'#': 51,
4: 52,
$: 52,
5: 53,
'%': 53,
6: 54,
'^': 54,
7: 55,
'&': 55,
8: 56,
'*': 56,
9: 57,
'(': 57,
a: 65,
A: 65,
b: 66,
B: 66,
c: 67,
C: 67,
d: 68,
D: 68,
e: 69,
E: 69,
f: 70,
F: 70,
g: 71,
G: 71,
h: 72,
H: 72,
i: 73,
I: 73,
j: 74,
J: 74,
k: 75,
K: 75,
l: 76,
L: 76,
m: 77,
M: 77,
n: 78,
N: 78,
o: 79,
O: 79,
p: 80,
P: 80,
q: 81,
Q: 81,
r: 82,
R: 82,
s: 83,
S: 83,
t: 84,
T: 84,
u: 85,
U: 85,
v: 86,
V: 86,
w: 87,
W: 87,
x: 88,
X: 88,
y: 89,
Y: 89,
z: 90,
Z: 90,
OS: 91,
ContextMenu: 93,
F1: 112,
F2: 113,
F3: 114,
F4: 115,
F5: 116,
F6: 117,
F7: 118,
F8: 119,
F9: 120,
F10: 121,
F11: 122,
F12: 123,
F13: 124,
F14: 125,
F15: 126,
F16: 127,
F17: 128,
F18: 129,
F19: 130,
F20: 131,
F21: 132,
F22: 133,
F23: 134,
F24: 135,
NumLock: 144,
ScrollLock: 145,
VolumeMute: 181,
VolumeDown: 182,
VolumeUp: 183,
';': 186,
':': 186,
'=': 187,
'+': 187,
',': 188,
'<': 188,
'-': 189,
_: 189,
'.': 190,
'>': 190,
'/': 191,
'?': 191,
'`': 192,
'~': 192,
'[': 219,
'{': 219,
'\\': 220,
'|': 220,
']': 221,
'}': 221,
"'": 222,
'"': 222,
Meta: 224,
AltGraph: 225,
Attn: 246,
CrSel: 247,
ExSel: 248,
EraseEof: 249,
Play: 250,
ZoomOut: 251,
```
26 English letters ignore case. At present, only one shortcut key can be registered for a command. If you don't need to register a shortcut key, fill in the blank string.
The second parameter is the shortcut key name, and the shortcut key mapping is the key value of the keyboard event
The case of 26 English letters is ignored. At present, only one shortcut key can be registered for a command. If you do not need to register shortcut keys, you can fill in the blank string.
Metakey is the same as controlkey. Just write control.
At present, the third parameter can only obtain store, which needs to be modified later. In version 0.2.0, the second parameter can obtain config. At the same time, the commander does not export from index, but obtains it from config when it needs to be used.
At present, the third parameter can only get store, which needs to be modified later. The second parameter in version 0.2.0 can obtain config. At the same time, the commander does not export from the index. If necessary, it can be obtained from config.
The last parameter is the display name.
### Right click menu
The right-click menu can be customized:
```js
//Custom right click
const contextMenuState = config.getContextMenuState();
const unmountContextMenu = contextMenuState.unmountContextMenu;
const commander = config.getCommanderRegister();
const contextMenuState = config. getContextMenuState();
const unmountContextMenu = contextMenuState. unmountContextMenu;
const commander = config. getCommanderRegister();
const ContextMenu = () => {
const handleclick = () => {
unmountContextMenu();
};
const forceUpdate = useState(0)[1];
contextMenuState.forceUpdate = () => {
contextMenuState. forceUpdate = () => {
forceUpdate((pre) => pre + 1);
};
return (
<div
style={{
left: contextMenuState.left,
top: contextMenuState.top,
left: contextMenuState. left,
top: contextMenuState. top,
position: 'fixed',
background: 'rgb(24, 23, 23)',
}}
@@ -471,7 +218,7 @@ background: 'rgb(24, 23, 23)',
<div
style={{ width: '100%' }}
onClick={() => {
commander.exec('redo');
Commander exec('redo');
handleclick();
}}
>
@@ -480,7 +227,7 @@ handleclick();
</div>
);
};
contextMenuState.contextMenu = <ContextMenu></ContextMenu>;
contextMenuState. contextMenu = <ContextMenu></ContextMenu>;
```
Get the contextmenustate first. There is an unmountcontextmenu on the contextmenustate, which is the method to close the right-click menu.
Therefore, you need to call close after clicking.
@@ -488,106 +235,16 @@ At the same time, the left and top above are the right-click positions.
In addition, you also need to add a strong brush assignment to forceupdate in the component to follow when the component moves.
### Function development
#### Function import
The function import is made into an object and placed in initfunctionmap
Import the function into an object and put it into initfunctionmap
```js
initFunctionMap: functionMap,
```
#### Function development
The key name will be displayed, so the key name is unique.
Its values are two objects, one is the function content FN, and the other is the configuration item config (the function name needs to be passed in for display above 0.10.0).
Each configuration in the array in config will be displayed for the user to configure. Name is the display name. Data represents where to get the data. You can choose to get it from input, data source and context (CTX). In addition, there is a special pop-up window (modal).
The receive in options indicates which key args will get the value from.
Multi indicates whether multiple option configurations are allowed.
Two functions changeuservalue and changeuservaluerecord are written in dooringx lib. The first function will make the obtained results into an array. If it is not multi, the first result will be taken. The second function will make the results into objects. For example, if the user selects Keya in the data source, the key value pair of the data source will be returned as an object.
FN, the first CTX parameter represents the context. If there is a conversion function, it may need to be used (for example, the result of the first function should be exported to the following functions)
The second parameter next needs to be executed after running, otherwise the event chain will not exit in the function all the time.
The third parameter config can get the entire config object.
The fourth parameter args is filled in by the user and will be returned according to the fields filled in options.
The fifth is eventlist, which can obtain the parameters of the whole event chain.
The sixth parameter Iname can get the user's choice.
```js
General get request function:{
fn: (ctx, next, config, args, _eventList, iname) => {
Console.log (args, 'parameter x');
const userSelect = iname.data;
const urlVal = changeUserValue(
Userselect ['request URL'],
args,
'_url',
config,
ctx
; / / input datasource CTX / / datasource will get the value, and CTX will get the field on CTX
const paramSource = changeUserValueRecord(
//Settings can only be retrieved from datasource or CTX
Userselect ['request parameter'],
args,
'_origin',
config,
ctx
);
const ctxVal = changeUserValue(
Userselect ['return context field'],
args,
'_ctx',
config,
ctx
);
//Check whether the parameter exists
//All are arrays, and non multi takes the first one.
const url = urlVal[0];
if (!url) {
return next();
}
const ctxKey = ctxVal[0];
axios
.get(url, {
params: {
...paramSource,
},
})
.then((res) => {
const data = res.data;
ctx[ctxKey] = data;
next();
})
.catch((e) => {
console.log(e);
next();
});
},
config: [
{
Name: 'request URL',
data: ['dataSource', 'ctx', 'input'],
options: {
receive: '_url',
multi: false,
},
},
{
Name: 'request parameters',
data: ['dataSource', 'ctx'],
options: {
receive: '_origin',
multi: true,
},
},
{
Name: 'return context field',
data: ['input'],
options: {
receive: '_ctx',
multi: false,
},
},
],
Name: 'general get request function'
},
```
This section is waiting to be updated
#### Timing and function loading
If necessary, generally use:
```js
eventCenter.manualUpdateMap(cur, displayName, arr);
eventCenter. manualUpdateMap(cur, displayName, arr);
```
In the manual updatemap, the first is the time name, the second is the display name, and the third is the user's choice.
The first one in the manual updatemap is the time name, the second one is the display name, and the third one is user selection.
After updating the event center, you also need to update the store, and the result is subject to the store.

View File

@@ -12,21 +12,7 @@ dooringx-lib的插件需要一个类型为`Partial<InitConfig>`的对象。
userConfigMerge不是所有属性都会合并部分属性会进行覆盖。
```
* 部分无法合并属性如果b传了会以b为准
* initstore不合并
* leftallregistmap合并
* leftRenderListCategory合并
* rightRenderListCategory合并
* rightGlobalCustom 不合并
* initComponentCache合并
* initFunctionMap合并
* initDataCenterMap合并
* initCommandModule合并
* initFormComponents合并
```
config支持部分配置异步导入比如左侧分类等这个是实验性功能所以不推荐这么做。
### 左侧面板
@@ -34,30 +20,12 @@ config支持部分配置异步导入比如左侧分类等这个是实验
左侧面板传入leftRenderListCategory即可。
```js
leftRenderListCategory: [
{
type: 'basic',
icon: <HighlightOutlined />,
displayName: '基础组件',
},
{
type: 'xxc',
icon: <ContainerOutlined />,
custom: true,
customRender: <div>我是自定义渲染</div>,
},
],
```
type是分类左侧组件显示在哪个分类由该字段决定。
icon则是左侧分类小图标。
当custom为true时可以使用customRender自定义渲染。
### 左侧组件
### 插件导入
@@ -65,27 +33,10 @@ icon则是左侧分类小图标。
左侧组件支持同步导入或者异步导入。
```js
const LeftRegistMap: LeftRegistComponentMapItem[] = [
{
type: 'basic',
component: 'button',
img: 'icon-anniu',
displayName: '按钮',
urlFn: () => import('./registComponents/button'),
},
];
```
如果需要异步导入组件则需要填写urlFn需要一个返回promise的函数。也可以支持远程载入组件只要webpack配上就行了。
如果需要同步导入组件则需要将组件放入配置项的initComponentCache中这样在载入时便会注册进componentRegister里。
```js
initComponentCache: {
modalMask: { component: MmodalMask },
},
```
### 组件编写
@@ -178,45 +129,10 @@ useDynamicAddEventCenter第一个参数是render的四个参数组成的对象
函数由组件抛出,可以加载到事件链上。比如,注册个改变文本函数,那么我可以在任意组件的时机中去调用该函数,从而触发该组件改变文本。
函数注册需要放入useEffect中,在组件卸载时需要卸载函数!否则会导致函数越来越多
函数注册需要放入useEffect中。目前不需要主动卸载,但在和弹窗上函数通信时,可能需要在预览环境卸载,否则可能第二次执行不生效
注意id要带上组件id因为一个组件可以拖出n个组件生成n个函数。
```js
useEffect(() => {
const functionCenter = eventCenter.getFunctionCenter();
const unregist = functionCenter.register(
`${pr.data.id}+改变文本函数`,
async (ctx, next, config, args, _eventList, iname) => {
const userSelect = iname.data;
const ctxVal = changeUserValue(
userSelect['改变文本数据源'],
args,
'_changeval',
config,
ctx
);
const text = ctxVal[0];
setText(text);
next();
},
[
{
name: '改变文本数据源',
data: ['ctx', 'input', 'dataSource'],
options: {
receive: '_changeval',
multi: false,
},
},
],
`${pr.data.id}+改变文本函数`
);
return () => {
unregist();
};
}, []);
```
函数中参数与配置见后面函数开发。
@@ -225,14 +141,6 @@ useEffect(() => {
右侧面板的配置和左侧面板一样:
```js
export interface RightMapRenderListPropsItemCategory {
type: string;
icon: ReactNode;
custom?: boolean;
customRender?: (type: string, current: IBlockType) => ReactNode;
}
```
type会影响左侧组件在开发时第三个参数的键名。那个键名中即代表该右侧中展示的type。
@@ -371,174 +279,7 @@ export default undo;
```
第一个参数是注册名。
第二个参数是快捷键名快捷键映射是键盘事件key值
```js
Cancel: 3,
Help: 6,
Backspace: 8,
Tab: 9,
Clear: 12,
Enter: 13,
Shift: 16,
Control: 17,
Alt: 18,
Pause: 19,
CapsLock: 20,
Escape: 27,
Convert: 28,
NonConvert: 29,
Accept: 30,
ModeChange: 31,
' ': 32,
PageUp: 33,
PageDown: 34,
End: 35,
Home: 36,
ArrowLeft: 37,
ArrowUp: 38,
ArrowRight: 39,
ArrowDown: 40,
Select: 41,
Print: 42,
Execute: 43,
PrintScreen: 44,
Insert: 45,
Delete: 46,
0: 48,
')': 48,
1: 49,
'!': 49,
2: 50,
'@': 50,
3: 51,
'#': 51,
4: 52,
$: 52,
5: 53,
'%': 53,
6: 54,
'^': 54,
7: 55,
'&': 55,
8: 56,
'*': 56,
9: 57,
'(': 57,
a: 65,
A: 65,
b: 66,
B: 66,
c: 67,
C: 67,
d: 68,
D: 68,
e: 69,
E: 69,
f: 70,
F: 70,
g: 71,
G: 71,
h: 72,
H: 72,
i: 73,
I: 73,
j: 74,
J: 74,
k: 75,
K: 75,
l: 76,
L: 76,
m: 77,
M: 77,
n: 78,
N: 78,
o: 79,
O: 79,
p: 80,
P: 80,
q: 81,
Q: 81,
r: 82,
R: 82,
s: 83,
S: 83,
t: 84,
T: 84,
u: 85,
U: 85,
v: 86,
V: 86,
w: 87,
W: 87,
x: 88,
X: 88,
y: 89,
Y: 89,
z: 90,
Z: 90,
OS: 91,
ContextMenu: 93,
F1: 112,
F2: 113,
F3: 114,
F4: 115,
F5: 116,
F6: 117,
F7: 118,
F8: 119,
F9: 120,
F10: 121,
F11: 122,
F12: 123,
F13: 124,
F14: 125,
F15: 126,
F16: 127,
F17: 128,
F18: 129,
F19: 130,
F20: 131,
F21: 132,
F22: 133,
F23: 134,
F24: 135,
NumLock: 144,
ScrollLock: 145,
VolumeMute: 181,
VolumeDown: 182,
VolumeUp: 183,
';': 186,
':': 186,
'=': 187,
'+': 187,
',': 188,
'<': 188,
'-': 189,
_: 189,
'.': 190,
'>': 190,
'/': 191,
'?': 191,
'`': 192,
'~': 192,
'[': 219,
'{': 219,
'\\': 220,
'|': 220,
']': 221,
'}': 221,
"'": 222,
'"': 222,
Meta: 224,
AltGraph: 225,
Attn: 246,
CrSel: 247,
ExSel: 248,
EraseEof: 249,
Play: 250,
ZoomOut: 251,
```
第二个参数是快捷键名快捷键映射是键盘事件key值
26个英文字母是忽略大小写的一个命令目前只能注册一个快捷键。不需要注册快捷键则填空字符串即可。
@@ -612,113 +353,7 @@ initFunctionMap: functionMap,
#### 函数开发
键名会显示出来所以键名是唯一的。
它的值是2个对象一个是函数内容fn一个是配置项config (0.10.0以上还需要传入函数名称,用于显示)。
config中的数组里每个配置会显示出来让用户去配置name则是展示名字data代表数据去哪里获取可以选择从输入框input数据源dataSource,上下文ctx中获取另外还有个特殊的弹窗modal
options中的receive表示会从args哪个键上获取该值。
multi代表是否允许多个选项配置。
dooringx-lib中写好了2个函数changeUserValue与changeUserValueRecord第一个函数会将得到的结果做成数组如果非multi则取第一个结果就行。而第二个函数会将结果做成对象比如用户在数据源中选了keya那么就会把数据源的键值对作为个对象返回。
fn中第一个ctx参数代表上下文如果有转换函数之类可能需要使用比如要把第一个函数的结果导给后面的函数
第二个参数next是需要运行完毕后执行的否则事件链会一直在该函数中不退出。
第三个参数config就可以拿到整个config对象。
第四个参数args是用户填写的参数会根据options里填写的字段进行返回。
第五个是eventList可以获取整个事件链的参数。
第六个参数iname可以拿到用户的选择项。
```js
通用GET请求函数: {
fn: (ctx, next, config, args, _eventList, iname) => {
console.log(args, '参数x');
const userSelect = iname.data;
const urlVal = changeUserValue(
userSelect['请求url'],
args,
'_url',
config,
ctx
); // input datasource ctx //datasource会去取值 ctx取ctx上字段
const paramSource = changeUserValueRecord(
// 设定只能从datasource或者ctx里取
userSelect['请求参数'],
args,
'_origin',
config,
ctx
);
const ctxVal = changeUserValue(
userSelect['返回上下文字段'],
args,
'_ctx',
config,
ctx
);
// 检查参数是否存在
// 都是数组非multi则取第一个。
const url = urlVal[0];
if (!url) {
return next();
}
const ctxKey = ctxVal[0];
axios
.get(url, {
params: {
...paramSource,
},
})
.then((res) => {
const data = res.data;
ctx[ctxKey] = data;
next();
})
.catch((e) => {
console.log(e);
next();
});
},
config: [
{
name: '请求url',
data: ['dataSource', 'ctx', 'input'],
options: {
receive: '_url',
multi: false,
},
},
{
name: '请求参数',
data: ['dataSource', 'ctx'],
options: {
receive: '_origin',
multi: true,
},
},
{
name: '返回上下文字段',
data: ['input'],
options: {
receive: '_ctx',
multi: false,
},
},
],
name: '通用GET请求函数'
},
```
该部分等待更新
#### 时机与函数装载

View File

@@ -8,7 +8,7 @@ nav:
---
### What is dooringx lib?
Dooringx lib is the base of dooringx and a visual drag and drop framework with dooringx plug-ins removed.
Dooring x lib provides its own set of data flow event mechanism, pop-up window and other solutions, which can enable you to customize and develop your own visual drag and drop platform faster.
Dooringx lib provides its own set of data flow event mechanism, pop-up window and other solutions, which allows you to customize and develop your own visual drag and drop platform faster.
### How does dooringx lib work?
Dooringx lib maintains a set of data flow at runtime, which is mainly divided into JSON data part, left component part, right configuration item part, shortcut key part, pop-up window part, event and function part and data source part.
In addition to providing basic drag, move, zoom, select all, rotate and other functions, it can also use exposed components. If you feel that the components are not customized enough, you can adjust the style or rewrite it yourself.
@@ -18,12 +18,7 @@ Install using NPM or yarn
```bash
npm i dooringx-lib
```
Dooring x lib provides two containers for editing, which can be used as needed.
One is an ordinary container and the other is an iframe container. These two containers are slightly different in some implementations.
If you use a normal container, that is, the div that is normal when editing is not iframe, while if you use iframe, you will see the iframe content when editing. When previewing, use the preview component, and the preview can be placed in any container, including iframe.
It is recommended to use iframe to view the preview during preview. If there is a pop-up window, exceptions will be displayed in non iframe or PC.
The iframe container may have a slight delay in operation because it uses PostMessage communication. If the style isolation requirements are not high, you can use ordinary containers, and the preview style can be normal.
Common container usage reference Demo:
Reference Demo:
```js
import {
RightConfig,
@@ -94,101 +89,6 @@ style={{ position: 'fixed', bottom: '60px', right: '450px', zIndex: 100 }}
);
}
```
Iframe container use reference Demo:
index.tsx
```js
import {
RightConfig,
useStoreState,
innerContainerDragUp,
LeftConfig,
IframeContainerWrapper,
Control,
useIframeHook,
IframeTarget,
} from 'dooringx-lib';
import { useContext } from 'react';
import { configContext } from '@/layouts';
import { useCallback } from 'react';
import { PREVIEWSTATE } from '@/constant';
export const HeaderHeight = '40px';
export default function IndexPage() {
const config = useContext(configContext);
const subscribeFn = useCallback(() => {
localStorage.setItem(PREVIEWSTATE, JSON.stringify(config.getStore().getData()));
}, [config]);
const [state] = useStoreState(config, subscribeFn);
useIframeHook(`${location.origin}/container`, config);
return (
<div {...innerContainerDragUp(config, true)}>
<div style={{ height: HeaderHeight }}>
head
<button
onClick={() => {
window.open('/iframe');
}}
>
go preview
</button>
<button
onClick={() => {
window.open('/preview');
}}
>
go preview
</button>
</div>
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: `calc(100vh - ${HeaderHeight})`,
width: '100vw',
}}
>
<div style={{ height: '100%' }}>
<LeftConfig config={config}></LeftConfig>
</div>
<IframeContainerWrapper
config={config}
extra={
<Control
config={config}
style={{ position: 'fixed', bottom: '60px', right: '450px', zIndex: 100 }}
></Control>
}
>
<IframeTarget
config={config}
iframeProps={{
src: '/container',
}}
></IframeTarget>
</IframeContainerWrapper>
<div className="rightrender" style={{ height: '100%' }}>
<RightConfig state={state} config={config}></RightConfig>
</div>
</div>
</div>
);
}
```
Container Routing:
```js
import { configContext } from '@/layouts';
import { useContext } from 'react';
import { IframeContainer } from 'dooringx-lib';
function ContainerPage() {
const config = useContext(configContext);
return (
<div>
<IframeContainer config={config} context="edit"></IframeContainer>
</div>
);
}
export default ContainerPage;
```
Preview iframe:
```html
<div

View File

@@ -33,18 +33,7 @@ dooringx-lib 在运行时维护一套数据流主要分为json数据部分
```bash
npm i dooringx-lib
```
dooringx-lib在编辑时提供两种容器可以根据需要选择使用。
一种是普通容器一种是iframe容器这2种容器在某些实现上略有不同。
使用普通容器即在编辑时为普通的div并非iframe而使用iframe则编辑时看见的为iframe内容。在预览时使用preview组件preview可以放到任何容器包括去使用iframe查看。
建议预览时使用iframe查看preview如果有弹窗在非iframe或pc中会显示异常。
iframe容器由于使用postmessage通信所以在操作上可能会有略微延迟。如果对样式隔离要求不高可以使用普通容器预览的样式正常即可。
普通容器使用参考demo:
参考demo:
```js
import {
@@ -125,114 +114,6 @@ export default function IndexPage() {
```
iframe容器使用参考demo
index.tsx
```js
import {
RightConfig,
useStoreState,
innerContainerDragUp,
LeftConfig,
IframeContainerWrapper,
Control,
useIframeHook,
IframeTarget,
} from 'dooringx-lib';
import { useContext } from 'react';
import { configContext } from '@/layouts';
import { useCallback } from 'react';
import { PREVIEWSTATE } from '@/constant';
export const HeaderHeight = '40px';
export default function IndexPage() {
const config = useContext(configContext);
const subscribeFn = useCallback(() => {
localStorage.setItem(PREVIEWSTATE, JSON.stringify(config.getStore().getData()));
}, [config]);
const [state] = useStoreState(config, subscribeFn);
useIframeHook(`${location.origin}/container`, config);
return (
<div {...innerContainerDragUp(config, true)}>
<div style={{ height: HeaderHeight }}>
head
<button
onClick={() => {
window.open('/iframe');
}}
>
go preview
</button>
<button
onClick={() => {
window.open('/preview');
}}
>
go preview
</button>
</div>
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: `calc(100vh - ${HeaderHeight})`,
width: '100vw',
}}
>
<div style={{ height: '100%' }}>
<LeftConfig config={config}></LeftConfig>
</div>
<IframeContainerWrapper
config={config}
extra={
<Control
config={config}
style={{ position: 'fixed', bottom: '60px', right: '450px', zIndex: 100 }}
></Control>
}
>
<IframeTarget
config={config}
iframeProps={{
src: '/container',
}}
></IframeTarget>
</IframeContainerWrapper>
<div className="rightrender" style={{ height: '100%' }}>
<RightConfig state={state} config={config}></RightConfig>
</div>
</div>
</div>
);
}
```
container 路由:
```js
import { configContext } from '@/layouts';
import { useContext } from 'react';
import { IframeContainer } from 'dooringx-lib';
function ContainerPage() {
const config = useContext(configContext);
return (
<div>
<IframeContainer config={config} context="edit"></IframeContainer>
</div>
);
}
export default ContainerPage;
```
预览时preview套iframe:

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili
* @Date: 2021-07-07 14:35:38
* @LastEditors: yehuozhili
* @LastEditTime: 2022-04-24 00:44:25
* @LastEditTime: 2022-04-24 20:42:01
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\registComponents\button.tsx
*/
@@ -36,7 +36,6 @@ function ButtonTemp(pr: ComponentRenderConfigProps) {
useEffect(() => {
let unRegist = () => {};
if (op1) {
console.log('kkk');
const functionCenter = eventCenter.getFunctionCenter();
unRegist = functionCenter.register({
id: `${pr.data.id}+changeText`,