Skip to content

开发进阶

使用三方依赖

编写的组件代码中,支持使用三方依赖,开发者只需要在代码中导入三方库,框架会根据代码中使用的依赖自动安装,不用自己手动安装。

举个例子,在代码中使用 antd 库。

jsx
import React from 'react';
import { Button } from 'antd';

export default function Demo({ title, context: { id } }) {
  return (
    <div data-id={id} className="title">
      {title}
      <Button type="primary">按钮</Button>
    </div>
  );
}

alt text

使用 material UI 组件

jsx
import React from 'react';
import Button from '@mui/material/Button';

export default function Demo({ title, context: { id } }) {
  return (
    <div data-id={id} className="title">
      {title}
      <Button variant="contained">按钮</Button>
    </div>
  );
}

alt text

使用 charts 图表库

jsx
import React from 'react';
import ReactECharts from 'echarts-for-react';

export default function Demo() {
  return (
    <ReactECharts
      option={{
        xAxis: {
          type: 'category',
          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
        },
        yAxis: {
          type: 'value',
        },
        series: [
          {
            data: [120, 200, 150, 80, 70, 110, 130],
            type: 'bar',
          },
        ],
      }}
      notMerge={true}
      lazyUpdate={true}
      theme={'theme_name'}
    />
  );
}

alt text

注意:导出的组件根元素必须有 data-id 这个属性,绑定 context 中 id 属性,这个属性是用来支持在编辑器中选择当前组件,修改组件属性使用的。

自定义属性

如果组件需要支持动态修改属性,也是支持的,下面给大家演示一下。

假设封装一个按钮组件,需要对外支持动态修改按钮文本、禁用、主题等功能。

这里使用 antd 的按钮为例,就不自己封装一个组件了。

jsx
import React from 'react';
import { Button } from 'antd';

export default function Demo({ text, disabled, type, context: { id } }) {
  return (
    <Button data-id={id} disabled={disabled} type={type}>
      {text}
    </Button>
  );
}

和普通 React 组件一样,可以从 props 中获取参数,绑定到组件中。

然后修改 config.js 文件

js
/**
 * 组件配置和属性值,默认需要导出一个模块
 */
export default {
    // 组件属性配置JSON
    attrs: [{
            type: 'Title',
            label: '基础配置',
            name: 'base',
        },
        {
            type: 'Input',
            label: '文本',
            name: 'text',
        },
        {
            type: 'Switch',
            label: '禁用',
            name: 'disabled',
        },
        {
            type: 'Select',
            label: '类型',
            name: 'type',
            props: {
                options: [{
                        label: '默认',
                        value: 'default'
                    },
                    {
                        label: '主要',
                        value: 'primary'
                    },
                ],
            },
        },
    ],
    config: {
        // 组件默认属性值
        props: {
            text: 'hello',
            disabled: false,
            type: 'default',
        },
        // 组件样式
        style: {},
        api: {},
    },
    // 组件事件
    events: [],
    methods: [],
};

这里的代码对应右侧的配置表单

alt text

attrs 表示当前组件对外暴露的配置项

type 字段表示配置的组件类型

  • Title 表示标题
  • Variable表示支持绑定变量
  • Input表示文本输入框
  • InputNumber表示数字输入框
  • Select表示下拉框
  • Switch表示切换组件
  • Json表示 json 输入框

这些名称和 antd form 表单组件名称保持一致。

label 表示当前配置的中文描述

name 表示当前配置的名称,和组件的 props 参数保持一致

config.props 配置对应组件参数默认值,比如现在按钮的默认文本是 hello

如果想让组件的某个属性,绑定动态变量,可以把类型设置为 Variable ,比如把上面的按钮文本支持绑定变量。把 type 的值由 Input 改为 Variable 就行了。

alt text

暴露方法

如果组件需要对外暴露方法在事件流里调用,可以使用 react 中的 useImperativeHandle 对外暴露方法。

举个例子:上面的按钮对外导出一个开始 loading 方法。

修改代码如下

jsx
import React, {
  useState, 
  useImperativeHandle 
} from 'react';
import { Button } from 'antd';

export default function Demo(
  { text, disabled, type, context: { id } },
  ref, 
) {
  const [loading, setLoading] = useState(false); 

  useImperativeHandle(ref, () => { 
    return { 
      startLoading: () => { 
        setLoading(true); 
      }, 
    }; 
  }); 

  return (
    <Button
      data-id={id}
      disabled={disabled}
      type={type}
      loading={loading} 
    >
      {text}
    </Button>
  );
}

config.js 中的 methods 属性添加值

js
  /**
   * 组件配置和属性值,默认需要导出一个模块
   */
  export default {
      // 组件属性配置JSON
      attrs: [{
              type: 'Title',
              label: '基础配置',
              name: 'base',
          },
          {
              type: 'Input',
              label: '文本',
              name: 'text',
          },
          {
              type: 'Switch',
              label: '禁用',
              name: 'disabled',
          },
          {
              type: 'Select',
              label: '类型',
              name: 'type',
              props: {
                  options: [{
                          label: '默认',
                          value: 'default'
                      },
                      {
                          label: '主要',
                          value: 'primary'
                      },
                  ],
              },
          },
      ],
      config: {
          // 组件默认属性值
          props: {
              text: 'hello',
              disabled: false,
              type: 'default',
          },
          // 组件样式
          style: {},
          api: {},
      },
      // 组件事件
      events: [],
      methods: [{ 
          title: '开始loading', 
          name: 'startLoading' // 这里要和导出的方法名保持一致 
      }], 
  };

在编辑器的事件流里可以选到这个组件方法了

alt text

alt text

暴露事件

自定义组件也支持对外暴露事件

举个例子:

按钮对外暴露点击事件绑定事件流

jsx
import React, { useState, useImperativeHandle } from 'react';
import { Button } from 'antd';

export default function Demo(
  {
    text,
    disabled,
    type,
    onClick, 
    context: { id }
  },
  ref
) {

  const [loading, setLoading] = useState(false);

  useImperativeHandle(ref, () => {
    return {
      startLoading: () => {
        setLoading(true);
      }
    }
  })

  return (
    <Button
      data-id={id}
      disabled={disabled}
      type={type}
      loading={loading}
      onClick={() => { 
       onClick && onClick(); 
      }} 
    >
      {text}
    </Button>
  );
}

修改 config.js 文件

js
/**
 * 组件配置和属性值,默认需要导出一个模块
 */
export default {
    // 组件属性配置JSON
    attrs: [{
            type: 'Title',
            label: '基础配置',
            name: 'base'
        },
        {
            type: 'Variable',
            label: '文本',
            name: 'text'
        },
        {
            type: 'Switch',
            label: '禁用',
            name: 'disabled'
        },
        {
            type: 'Select',
            label: '类型',
            name: 'type',
            props: {
                options: [{
                        label: '默认',
                        value: 'default'
                    },
                    {
                        label: '主要',
                        value: 'primary'
                    }
                ]
            }
        },
    ],
    config: {
        // 组件默认属性值
        props: {
            text: "hello",
            disbaled: false,
            type: 'default',
        },
        // 组件样式
        style: {},
        api: {}
    },
    // 组件事件
    events: [{ 
        name: '点击事件', 
        value: 'onClick' // 这里和传入的事件名保持一致 
    }], 
    methods: [{
        title: '开始loading',
        name: 'startLoading' // 这里要和导出的方法名保持一致 
    }]
};

在编辑器中给组件绑定点击事件

alt text

暴露数据

自定义组件还支持对外暴露数据,方便在脚本编辑器中使用。

可以使用 setCurComponentData 方法把数据暴露出去。

jsx
import React, { useState, useImperativeHandle } from 'react';
import { Button } from 'antd';

export default function Demo(
  {
    text,
    disabled,
    type,
    onClick,
    context: {
      id,
      setCurComponentData, 
    }
  },
  ref
) {

  const [loading, setLoading] = useState(false);

  useImperativeHandle(ref, () => {
    return {
      startLoading: () => {
        setLoading(true);
      }
    }
  })

  return (
    <Button
      data-id={id}
      disabled={disabled}
      type={type}
      loading={loading}
      onClick={() => {
        setCurComponentData('title', Date.now().toString()) 
        onClick && onClick();
      }}
    >
      {text}
    </Button>
  );
}

修改 config.js 配置文件

jsx
/**
* 组件配置和属性值,默认需要导出一个模块
*/
export default {
  // 组件属性配置JSON
  attrs: [
    {
      type: 'Title',
      label: '基础配置',
      name: 'base'
    },
    {
      type: 'Variable',
      label: '文本',
      name: 'text'
    },
    {
      type: 'Switch',
      label: '禁用',
      name: 'disabled'
    },
    {
      type: 'Select',
      label: '类型',
      name: 'type',
      props: {
        options: [
          { label: '默认', value: 'default' },
          { label: '主要', value: 'primary' }
        ]
      }
    },
  ],
  config: {
    // 组件默认属性值
    props: {
      text: "hello",
      disbaled: false,
      type: 'default',
    },
    // 组件样式
    style: {},
    api: {}
  },
  // 组件事件
  events: [{
    name: '点击事件',
    value: 'onClick'
  }],
  methods: [{
    title: '开始loading',
    name: 'startLoading' // 这里要和导出的方法名保持一致 
  }],
  exportKeys: [{ // [!code ++ ]
    key: 'title', // 这个key对应setCurComponent方法的第一个参数 // [!code ++ ] 
    name: '标题'// [!code ++ ]
  }]// [!code ++ ]
};

编辑器中就可以在脚本编辑器中使用到组件暴露出来的变量

举个例子,让当前组件的标题字段绑定这个变量

alt text

alt text

点击按钮后,按钮的文本会自动变化

alt text

数据联动

自定义组件中可以使用 useData 获取编辑器中传入的数据源

举个例子:自定义一个下拉框组件,下拉框的数据源来源于编辑器。

jsx
import React from 'react';
import { Select } from 'antd';

export default function Demo(
  {
    context: {
      id,
      useData,
    }
  }
) {

 // 可以调用refresh方法刷新数据
  const { list = [], loading, refresh } = useData();

  return (
    <Select
      data-id={id}
      options={list}
      loading={loading}
    />
  );
}

保存并预览

alt text

可以在右侧mock数据

alt text

可以在 config.js 里设置默认数据

js
/**
 * 组件配置和属性值,默认需要导出一个模块
 */
export default {
    // 组件属性配置JSON
    attrs: [],
    config: {
        // 组件默认属性值
        props: {},
        // 组件样式
        style: {},
        api: {
            source: [ 
                { 
                    "label": "选项1", 
                    "value": 1
                }, 
                { 
                    "label": "选项2", 
                    "value": 2
                }, 
                { 
                    "label": "选项3", 
                    "value": 3
                } 
            ] 
        }
    },
    // 组件事件
    events: [],
    methods: [],
    exportKeys: []
};

在编辑器中可以使用其他数据源,比如模型。

alt text

拖放组件到内部

自定义组件支持把其他组件拖入到内部,把drop绑定到支持拖放的组件上,渲染children。

jsx
import React from 'react';

export default function Demo(
  {
    context: {
      id,
      drop
    },
    children
  }
) {

  return (
    <div
      data-id={id}
      ref={drop}
    >
      {children}
    </div>
  );
}

修改 config.js ,开启拖放

js
/**
 * 组件配置和属性值,默认需要导出一个模块
 */
export default {
    // 组件属性配置JSON
    attrs: [],
    config: {
        // 组件默认属性值
        props: {},
        // 组件样式
        style: {},
        api: {}
    },
    // 组件事件
    events: [],
    methods: [],
    exportKeys: [],
    enableDrop: true, 
};

在编辑器里可以看到刚才开发的自定义支持拖放组件了

alt text

比如拖放一个基础表格到自定义组件中

alt text

样式

开发组件,可能会写样式,自定义组件中支持两种写样式的方式。 lesstailwindcss

less

index.jsx

jsx
import React from 'react';

export default function Demo(
  {
    context: {
      id,
    }
  }
) {
  return (
    <div
      data-id={id}
      className="title"
    >
      hello
    </div>
  );
}

index.less

less
@color: green;

.title {
  color: @color;
}

alt text

tailwindcss

目前AI生成的代码对 tailwindcss 支持的比较成熟,所以我们自定义组件中也支持使用 tailwindcss 所有特性。

jsx
import React from 'react';

export default function Demo(
  {
    context: {
      id,
    }
  }
) {
  return (
    <div
      data-id={id}
      className="text-red-500 hover:text-green-500"
    >
      hello
    </div>
  );
}

alt text

hover后

alt text

Released under the MIT License.