什么是组件?
组件是编辑器内的最小粒度, 也是编辑器功能实现中最重要的一员。可以把它比喻成一个积木,该积木拥有自己的形状、颜色、大小、合适的位置等。
同理,在网页设计中。一个组件就会拥有自己独特的样式、数据、事件、动画等。当然,它和其他组件也有相同的地方。所以,组件间会存在公用的样式、数据、属性、动画。由此可知,组件的编辑会进行私有和公有的区分。那么你肯定想到了,对于组件来说,同样会以此作为区分。
一、组件的核心属性
由上可知。我们可以将一个组件的属性定义为以下几个部分。
1.数据(data)
组件对外可编辑或可展示的数据。
2.样式(style)
组件对外可编辑或可展示的数据。
3.事件(event)
组件内部事件触发行为 与 组件通信、全局通信事件。
4.动画(animation)
组件动画行为。
二、组件的次要属性
组件本身携带用于逻辑判断、组件维护等属性。
1.版本(version)
组件版本控制。用于组件升级、回退等
2.类型(type)
组件类型区分。唯一值,用于布局、拖拽、组件特殊判断等。
3.布局(layout)
用于限制当前组件的可用布局类型。例如:可用与左右布局、全屏布局
4.可用模块(modules)
每个布局拥有多个模块,该属性用于限制组件,在对应布局下的可用模块有哪些。
三、组件的完整数据
以下是一个组件构成的案例代码。
export default {
version: '1.0.0', // 版本
type: WIDGET_SPE_TYPE.LEFT_MENU, // 类型
layout: [LAYOUT_KEY.LEFT_RIGHT, LAYOUT_KEY.FULL_SCREEN], // 可用布局
modules: {
[LAYOUT_KEY.LEFT_RIGHT]: [LEFT_RIGHT_MODULES.LEFT],
[LAYOUT_KEY.FULL_SCREEN]: [FULL_SCREEN_MODULES.CENTER]
}, // 可用布局下的可使用模块 布局: 模块
data: {
title: '左侧菜单',
icon: '', // 文章icon
params: {
cateKey: '' // 默认空为请求所有
}, // 文章请求参数 暂时只有type. 使用对象是防止请求参数复杂化后的处理
jumpUrl: '', // 文章跳转路径。默认会携带当前文章的id与类型
},
style: {
backgroundColor: ''
},
event: {
onMenuClick: {
bind: [], // 已绑定信息 结构 { id: 'xx', params }
label: '菜单点击'
},
onMenuCollapse: {
bind: [],
label: '菜单折叠'
}
}
};
四、组件数据、样式、事件的数据编辑
🤔 那么你可能要问了。组件的数据要这么编辑呢?
😃 这你就问对人了。组件的数据编辑与展示我们依赖于JS的特性: 对象引用,当然我们也可以使用object.defineProperty 或者 Proxy。在Vue3版本中。我们使用了ref代理整个数据对象。这也给它绑定上了proxy。
所以编辑和展示的我们使用的是同一份数据。对于数据、样式、事件的编辑,我们编辑的就是组件内的data、style、event。
对于以上数据。内部实现了一个通过el-form改造的属性编辑器propertyRender, 以用于属性编辑。
1.propertyRender
该组件主要支持以下几种类型的渲染。
Render渲染自定义编辑组件- 支持
Element-plus所有类型表单组件 - 支持自定义通用组件
- 支持错误处理(开发中.....)
所以我们在单个组件文件夹下存在editor.jsx文件。里面设置了Data、Style、Event的配置文件。以下是示例代码。
export const editor = [
{
prop: 'title',
type: ELEMENT_TYPE.INPUT,
label: '标题'
},
{
prop: 'icon',
label: '标题图标',
render: (form) => {
return (
<ImgSelector
v-model={form.icon}
/>
)
}
},
{
prop: 'jumpUrl',
type: ELEMENT_TYPE.INPUT, // 待实现参数绑定
label: '跳转路径',
attributes: {
placeholder: '请输入跳转地址'
}
},
{
prop: 'params',
label: '文章列表选择',
render: (form) => {
return (
<ArticleSelector
v-model={form.params}
/>
)
}
},
];
export const style = [
{
prop: 'backgroundColor',
type: STYLE_TYPE.COLOR_SELECTOR,
label: '背景颜色'
},
]
// 事件处理
export const event = [
{
prop: 'onMenuClick',
type: EVENT_TYPE.EVENT_SELECTOR,
label: '点击事件'
},
{
prop: 'onMenuCollapse',
type: EVENT_TYPE.EVENT_SELECTOR,
label: '展开收起'
}
]
我们可以看到我们在其中使用了多种不同的类型的属性编辑器。 ELEMENT_TYPE.INPUT 是自定义枚举类型。
ELEMENT_TYPE.INPUT: Element-plus自带的表单组件
ImgSelector: 组件自定义组件,使用Render渲染
STYLE_TYPE.COLOR_SELECTOR和 EVENT_TYPE.EVENT_SELECTOR: 共用属性编辑组件。
所以我们通过propertyRender就能编辑完成一个组件的所有属性, 不同的区别在于用户如何去正确配置。
五、一个组件的文件结构
组件如何使用?
细心的你一定发现了。前文似乎只介绍了属性结构,组件的编辑原理。但是如何使用并没有提起。不用着急,这会放在编辑器设计文档中进行详细介绍!