概览
魔方开发脚手架内置了一些通用组件:
Wrap 组件
我们对一些通用组件进行了二次封装,包括 UploadImg
、SelectColor
、UrlInput
和 Antd
的一些数据录入组件,封装后的组件名为 原组件名 + Wrap
的形式,封装的组件与原组件的区别如下:
- 简化组件的使用,通过
keyName
与dispatch
直连魔方编辑器的store
- 避免对象字面量的使用,避免组件重复渲染
代码示例
我们以 UploadImg
为例,confData.data.imgM
为卡片的图片数据,通过 UploadImg
组件更新数据:
import React from 'react';
import { UploadImgWrap } from '../../components/UploadImg';
type TProps = {
confData: any;
isDarkMode: boolean;
dispatch: React.Dispatch<any>;
};
const EditCard: React.FC<TProps> = ({ confData, dispatch }) => {
return (
<UploadImgWrap
img={confData.data.imgM}
valueType="auto"
keyName="data.imgM"
dispatch={dispatch}
note="建议压缩图片后上传"
/>
);
};
export default EditCard;
参数说明
keyName
为操作字段在store
中的路径,支持多层级,如data.imgM
、data.imgM.0.url
- 对象多层级路径
data.imgM
对应store
中confData.data.imgM
字段 - 数组多层级路径
data.img.0.url
对应store
中confData.data.img[0].url
字段
- 对象多层级路径
背后实现
受益于魔方编辑器 store
基于 immer.js
的设计,我们可以通过直接操作对象值的方式,实现数据的同步更新,而无需关心不可变对象的问题。
我们以 SelectColor
为例,来看看二次封装组件实现,你也可以通过这种方式,对一些通用组件进行二次封装。
import SelectColor from '../../components/SelectColor';
// 通过点号访问对象、数组属性值
const set = (data: any, keyName: string | number, value: any) => {
// 将属性名按照点号进行分割
const nameParts = String(keyName).split('.');
nameParts.forEach((part, index) => {
if (index === nameParts.length - 1) {
data[part] = value;
} else {
data = data[part]; // 逐级访问属性值
}
});
};
// 二次封装 SelectColor 组件
const SelectColorWrap: React.FC<{
title: string;
value: string;
keyName: string;
dispatch: React.Dispatch<any>;
[key: string]: any;
}> = React.memo(({ value, dispatch, keyName, ...params }) => {
return (
<SelectColor
value={value}
onChange={(e) =>
dispatch({
type: 'UPDATE_MODULE',
payload(draft: any) {
set(draft, keyName, e);
},
})
}
{...params}
/>
);
});