引言
本文将带你深入低代码平台设置区的实现细节,聚焦属性、样式、事件三大功能模块,结合完整代码与原理分析,揭秘如何让右侧面板成为组件的“万能遥控器”!
- 想要获取该项目的全部代码?可直接访问此仓库链接: 内附项目体验地址
- 🔗 github.com/LZY-Ricardo…
1. 设置区整体结构与分工
设置区(Setting)是组件属性、样式和事件的集中管理地。它通过分段切换(Segmented)实现三大功能区的自由切换:
- 属性:展示并编辑当前选中组件的业务属性
- 外观:支持样式的可视化与代码编辑
- 事件:预留事件绑定能力
核心入口代码如下:
import { useState } from 'react'
import { useComponentsStore } from '../../stores/components'
import { Segmented } from 'antd';
import ComponentAttr from './ComponentAttr'
import ComponentStyle from './ComponentStyle'
import ComponentEvent from './ComponentEvent'
export default function Setting() {
const { components } = useComponentsStore()
const [key, setKey] = useState('属性')
return (
<div>
<Segmented value={key} options={['属性', '外观', '事件']} block onChange={setKey}/>
<div className='pt-[20px]'>
{key === '属性' && <ComponentAttr/>}
{key === '外观' && <ComponentStyle/>}
{key === '事件' && <ComponentEvent/>}
</div>
</div>
)
}
2. 属性面板(ComponentAttr):组件属性的“魔法编辑器”
属性面板通过动态渲染表单,支持不同类型的属性编辑(如输入框、下拉框等),并与组件仓库实时联动。
import { useEffect } from 'react'
import { Form, Input, Select } from 'antd';
import { useComponentsStore } from '../../stores/components'
import { useComponentConfigStore } from '../../stores/component-config';
import type { ComponentSetter } from '../../stores/component-config';
export default function ComponentAttr() {
const [form] = Form.useForm();
const { curComponentId, curComponent, updateComponentProps } = useComponentsStore()
const { componentConfig } = useComponentConfigStore()
// 回显
useEffect(() => {
const data = form.getFieldsValue()
form.setFieldsValue({...data, ...curComponent?.props})
}, [curComponent])
if (!curComponent || !curComponentId) {
return null
}
function renderFormElement(setter: ComponentSetter) {
const { type, options } = setter
if (type === 'select') { // 下拉框
return <Select options={options} />
} else if (type === 'input') {
return <Input />
}
}
const valueChange = (values: any) => {
console.log(values)
}
return (
<Form form={form} onValuesChange={valueChange} labelCol={{ span: 8 }} wrapperCol={{ span: 14 }}>
<Form.Item label="组件id">
<Input disabled value={curComponentId}/>
</Form.Item>
<Form.Item label="组件名称">
<Input disabled value={curComponent.name}/>
</Form.Item>
<Form.Item label="组件描述">
<Input disabled value={curComponent.desc}/>
</Form.Item>
{/* 当前被选中的组件,允许修改的属性 */}
{
componentConfig[curComponent.name].setter?.map(setter => {
return (
<Form.Item name={setter.name} label={setter.label} key={setter.name}>
{renderFormElement(setter)}
</Form.Item>
)
})
}
</Form>
)
}
原理分析:
- 组件属性通过 setter 配置动态生成,支持灵活扩展。
- 表单回显与仓库数据实时同步,保证编辑体验流畅。
- 支持多类型表单控件,满足不同属性需求。
效果展示:
3. 样式面板(ComponentStyle):让组件“颜值爆表”
样式面板不仅支持表单化样式编辑,还集成了 Monaco Editor,支持 CSS 代码直编直改,极大提升开发者自由度。
import { Form, Input, InputNumber, Select } from 'antd';
import { useEffect, useState } from 'react';
import type { CSSProperties } from 'react';
import { useComponentConfigStore } from '../../stores/component-config';
import type { ComponentSetter } from '../../stores/component-config';
import { useComponentsStore } from '../../stores/components';
import CssEditor from './CssEditor';
import { debounce } from 'lodash-es';
import styleToObject from 'style-to-object';
export default function ComponentStyle() {
const [form] = Form.useForm();
const { curComponentId, curComponent, updateComponentStyles } = useComponentsStore();
const { componentConfig } = useComponentConfigStore();
const [css, setCss] = useState<string>(`.comp{\n\n}`);
useEffect(() => {
form.resetFields();
const data = form.getFieldsValue();
form.setFieldsValue({...data, ...curComponent?.styles});
setCss(toCSSStr(curComponent?.styles!))
}, [curComponent])
function toCSSStr(css: Record<string, any>) {
let str = `.comp {\n`;
for(let key in css) {
let value = css[key];
if(!value) {
continue;
}
if(['width', 'height'].includes(key) && !value.toString().endsWith('px')) {
value += 'px';
}
str += `\t${key}: ${value};\n`
}
str += `}`;
return str;
}
if (!curComponentId || !curComponent) return null;
function renderFormElememt(setting: ComponentSetter) {
const { type, options } = setting;
if (type === 'select') {
return <Select options={options} />
} else if (type === 'input') {
return <Input />
} else if (type === 'inputNumber') {
return <InputNumber />
}
}
function valueChange(changeValues: CSSProperties) {
if (curComponentId) {
updateComponentStyles(curComponentId, changeValues);
}
}
const handleEditorChange = debounce((value) => {
setCss(value);
let css: Record<string, any> = {};
try {
const cssStr = value.replace(/\/\*.*\*\//, '') // 去掉注释 /** */
.replace(/(\.?[^{]+{)/, '') // 去掉 .comp {
.replace('}', '');// 去掉 }
styleToObject(cssStr, (name, value) => {
css[name.replace(/-\w/, (item) => item.toUpperCase().replace('-', ''))] = value;
});
updateComponentStyles(curComponentId, {...form.getFieldsValue(), ...css});
} catch(e) {}
}, 500);
return (
<Form
form={form}
onValuesChange={valueChange}
labelCol={{ span: 8 }}
wrapperCol={{ span: 14 }}
>
{
componentConfig[curComponent.name]?.stylesSetter?.map(setter => (
<Form.Item key={setter.name} name={setter.name} label={setter.label}>
{renderFormElememt(setter)}
</Form.Item>
))
}
<div className='h-[200px] border-[1px] border-[#ccc] z-10'>
<CssEditor value={ css } onChange={handleEditorChange}/>
</div>
</Form>
)
}
原理分析:
- 支持表单化与代码化双模式编辑,满足不同开发者习惯。
- 样式 setter 配置灵活,支持扩展多种样式属性。
- CSS 代码编辑区与表单数据实时同步,提升体验。
效果展示:
4. 事件面板(ComponentEvent):扩展能力预留
目前事件面板为占位符,后续可扩展为事件绑定、交互逻辑配置等高级功能。
import React from 'react'
export default function ComponentEvent() {
return (
<div>ComponentEvent</div>
)
}
5. 设置区数据驱动机制
设置区的属性和样式编辑能力,均依赖于组件仓库的 setter 和 stylesSetter 配置: 当点击选中画布区域的组件时,右侧设置面板(setting)会展示该组件的属性,具体实现方式如下:
- 为每个组件对象新增了
setter属性,其类型为数组,用于存储该组件所有可修改的属性。 - 为每组对象新增了
stylesSetter数组,专门用于存放用户自定义的样式。这些自定义样式会通过style-to-object工具转换为对象(obj)格式,并嵌入到仓库的 JSON 数据中。
6. 总结
设置区通过属性、样式、事件三大模块,结合 setter/stylesSetter 配置,实现了灵活、可扩展的组件编辑体验。无论是业务属性、样式美化还是事件扩展,都能一站式搞定,让你的低代码平台“遥控器”更强大!(๑•̀ㅂ•́)و✧
项目所有代码均已整理至以下仓库,方便大家查看与使用:
→ 代码仓库地址内附项目体验地址