本文整体阐述自定义页面组件开发的开发步骤。
概述
开发自定义页面组件,一般分为三步:
开发满足功能的react组件。
配置自定义页面组件的prop和配置文件。
包装react组件,处理prop的加工传递。
步骤一、开发react组件
开发自定义页面组件,本质上是开发一个react组件,或者说形式上是一个react组件。
自定义页面组件包含桌面端组件和移动端组件,两者开发逻辑相同,区别是移动端组件只能使用taro组件库,而不能使用fusion等其它的组件库。
首先需要基于待开发组件的功能需求,开发一个react组件。组件需要的参数都通过prop传入,组件需要向外传递的数据或者触发的事件,通过函数prop以回调的形式传入,通过回调函数返回或者触发相关逻辑。
例如,一个简单的数字选择组件DemoComponent,需要以下prop:
title :一个用于展示的标题文本。
num: 一个受控数据。
onNumChange: num变化时的回调接口。
桌面端组件代码示例:
import React from 'react'; import { NumberPicker } from '@alifd/next'; const DemoComponent = (props: { title: string; num: number; onNumChange: (num) => void }) => { return ( <div> <span>{props.title}</span> <NumberPicker value={props.num} onChange={props.onNumChange} /> </div> ); }; export default DemoComponent;
移动端组件代码示例(使用taro组件库):
import React from 'react'; import { View, Input } from '@tarojs/components'; import '@tarojs/components/dist/taro-components/taro-components.css'; const DemoComponent = (props: { title: string; num: number; onNumChange: (num) => void }) => { return ( <View style={{ lineHeight: 1 }}> <View>Title:</View> <View>{props.title}</View> <View>InputNum:</View> <Input type={'number'} value={props.num} onInput={(e) => { if (e.detail.value) { props.onNumChange(parseInt(e.detail.value)); } else { props.onNumChange(undefined); } }} /> </View> ); };
步骤二、配置自定义页面组件的prop和配置文件
步骤一中开发了一个react组件DemoComponent,还不能在魔笔应用中使用,如果要放到魔笔中使用,还需要做自定义配置。
假设:
title是静态的,可以通过setter设置title。
num是动态的,可以通过setter设置一个实体字段。
配置文件关键部分如下:
configure: [
{
name: "title",
title: "标题",
setter: {
type: "text",
props: {
placeholder: '请输入标题'
},
},
},
{
name: "num",
title: "选择数字字段",
setter: {
type: "data-field",
props: {
supportFieldType: ["integer", "long", "decimal"],
},
},
},
],
此处配置了两个prop:
title
setter是text。
在属性设置器中的标题是 “标题”。
num
setter是data-field。
在属性设置器中的标题是 “选择数字字段”。
此处为了便于理解对应关系,prop的名字(title,num)和组件的prop是对应的。
另外配置文件中还有一个很重要的componentName字段,表示组件名称,必须是全局唯一的。
完整的配置文件如下:
export default {
version: "1.0",
isContainer: false,
canContain: false,
canDraging: true,
canDropIn: false,
canDropTo: true,
canHovering: true,
canOperating: true,
canSelecting: true,
title: "Demo",
componentName: "DemoComponent",
// 高级 | 其他
category: "基础",
configure: [
{
name: "title",
title: "标题",
setter: {
type: "text",
props: {
placeholder: '请输入标题'
},
},
},
{
name: "num",
title: "选择数字字段",
setter: {
type: "data-field",
props: {
supportFieldType: ["integer", "long", "decimal"],
},
},
},
],
};
步骤三、包装、处理、传递prop
将魔笔的prop转化为组件需要的prop,并设置合理回调接口。具体内容如下:
处理传递prop。
处理回调响应。
设置配置文件。
设置监听。
步骤二、设计配置自定义页面组件的prop和配置文件中配置了两个prop, 如下:
const MobiComponent = (props: { title: string; num: any }) => {
const { title, num } = props;
return <DemoComponent />;
};
处理title prop
title是静态的文本类型,直接传递过去即可。
const MobiComponent = (props: { title: string; num: any }) => {
const { title, num } = props;
return <DemoComponent title={title}/>;
};
处理num prop
num是一个实体字段,在设计时,没有对应的数据,在运行时,才能获取数据。此时需要使用API,区分状态获取数据了。
import { useApi } from "../../../api/createApi";
const MobiComponent = (props: { title: string; num: any }) => {
// 获取api
const api = useApi(props);
const { title, num } = props;
// 设计时 就用0
let numValue = 0;
if(api.isPreview(props)) {
// 运行时 获取具体数据
numValue = api.getDcValue(props, {key: 'num'});
}
return <DemoComponent title={title} num={numValue}/>;
};
如上实现,就可以在设计时用0代替,在运行时使用真正的数据。
处理回调响应
DemoComponent会修改num,通过onNumChange
回调返回修改后的值,在回调中需要调用API更新num对应的数据字段。
const MobiComponent = (props: { title: string; num: any }) => {
// 获取api
const api = useApi(props);
const { title, num } = props;
// 设计时 就用0
let numValue = 0;
if (api.isPreview(props)) {
// 运行时 获取具体数据
numValue = api.getDcValue(props, { key: "num" });
}
return (
<DemoComponent
title={title}
num={numValue}
onNumChange={(num) => {
// 把回调的num,通过api,在设置回魔笔应用,key: "num" 确定了修改传入的num的数值
api.setDcValue(props, { key: "num", uiValue: num });
}}
/>
);
};
设置配置文件
通过组件的config属性将配置文件和组件关联起来。
import config from "./config";
MobiComponent.config = config;
设置监听
当前示例开发的是一个受控组件,当数据变化时也需要修改num。魔笔应用是用mobx监听的数据,这一步引入mobx。
import { observer } from "mobx-react";
const MobiComponent = observer((props: { title: string; num: any }) => {
});
完整的组件代码示例
配置文件:
export default {
version: "1.0",
isContainer: false,
canContain: false,
canDraging: true,
canDropIn: false,
canDropTo: true,
canHovering: true,
canOperating: true,
canSelecting: true,
title: "Demo",
componentName: "DemoComponent",
// 高级 | 其他
category: "基础",
configure: [
{
name: "title",
title: "标题",
setter: {
type: "text",
props: {
placeholder: '请输入标题'
},
},
},
{
name: "num",
title: "选择数字字段",
setter: {
type: "data-field",
props: {
supportFieldType: ["integer", "long", "decimal"],
},
},
},
],
};
组件代码:
import React from "react";
import { NumberPicker } from "@alifd/next";
import { useApi } from "../../../api/createApi";
import config from "./config";
import { observer } from "mobx-react";
const DemoComponent = (props: {
title: string;
num: number;
onNumChange: (num) => void;
}) => {
return (
<div>
<span>{props.title}</span>
<NumberPicker value={props.num} onChange={props.onNumChange} />
</div>
);
};
const MobiComponent = observer((props: { title: string; num: any }) => {
// 获取api
const api = useApi(props);
const { title, num } = props;
// 设计时 就用0
let numValue = 0;
if (api.isPreview(props)) {
// 运行时 获取具体数据
numValue = api.getDcValue(props, { key: "num" });
}
return (
<DemoComponent
title={title}
num={numValue}
onNumChange={(num) => {
// 把回调的num,通过api,在设置回魔笔应用,key: "num" 确定了修改传入的num的数值
api.setDcValue(props, { key: "num", uiValue: num });
}}
/>
);
});
MobiComponent.config = config;
export default MobiComponent;