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 { data = [], loading, refresh } = useData();

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

保存并预览

alt text

可以在右侧mock数据

alt text

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

js
/**
 * 组件配置和属性值,默认需要导出一个模块
 */
export default {
    // 组件属性配置JSON
    attrs: [],
    config: {
        // 组件默认属性值
        props: {},
        // 组件样式
        style: {},
        api: {
            sourceType: 'json', 
            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

样式 ​

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

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.