跳到主要内容

概览

魔方开发脚手架内置了一些通用组件:

Wrap 组件

我们对一些通用组件进行了二次封装,包括 UploadImgSelectColorUrlInputAntd 的一些数据录入组件,封装后的组件名为 原组件名 + Wrap 的形式,封装的组件与原组件的区别如下:

  • 简化组件的使用,通过 keyNamedispatch 直连魔方编辑器的 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.imgMdata.imgM.0.url
    • 对象多层级路径 data.imgM 对应 storeconfData.data.imgM 字段
    • 数组多层级路径 data.img.0.url 对应 storeconfData.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}
/>
);
});