Skip to content

快速上手

此文由官方文档转载

作者:CoCo中控台

简介

CoCo 编辑器已拥有了自定义控件功能,开发者可以使用 JS 编写属于自己的控件,实现特定的功能。比如实现密码输入框、多行文本输入框、查询天气功能等。

当然,也可以把控件提交给官方,官方通过审核后,上架到控件商城。

自定义控件有两种类型:

可见控件(VisibleWidget)

也就是界面控件,比如按钮、输入框、文本等。

文件格式为 .jsx,比如 text.jsx。

不可见控件(InvisibleWidget)

这类控件在舞台不可见,一般用于提供系统(原生)能力,所以也称为功能型控件,比如照相机控件、音频控件等。

文件格式为.js,比如camera.js。

控件文件

控件文件一般由两部分组成,控件类型定义 + 控件实体定义 以 闪烁按钮 控件(可见控件)的文件为例。 附件: 下载控件后,将 .txt 后缀去掉,语雀不支持.jsx文件上传,所以临时加的.txt后缀。

控件类型定义

js
// 控件类型定义
const types = {
  type: 'SAMPLE_BLINK_BUTTON_WIDGET',
  icon: 'https://static.codemao.cn/appcraft/extension-widgets/production/blink-button.svg',
  title: '闪烁按钮',
  isInvisibleWidget: false,
  isGlobalWidget: false,
  properties: [
    // ...
  ],
  methods: [
    // ...
  ],
  events: [
  	// ...
  ],
};

字段解释:

字段解释举例
type控件类型,全局唯一,大写字母加下划线组成SAMPLE_BLINK_BUTTON_WIDGET
icon控件图标的链接,一般使用 SVG。https://static.codemao.cn/appcraft/extension-widgets/production/blink-button.svg
title控件的显示名称闪烁按钮
isInvisibleWidget是否不可见控件false
properties控件的属性列表按钮的宽度
methods控件的方法列表发送 Get 请求
events控件的事件列表当按钮被点击

控件属性(properties)

代码如下:

js
const types = {
  properties: [
    {
      key: '__width', // 内置属性
      label: '宽度',
      valueType: 'number', // 数字类型
      defaultValue: 68,
    },
    {
      key: '__height', // 内置属性
      label: '高度',
      valueType: 'number', // 数字类型
      defaultValue: 36,
    },
    {
      key: 'content',
      label: '按钮文案',
      valueType: 'string', // 字符串类型
      defaultValue: '按钮',
    },
    {
      key: 'disabled',
      label: '是否禁用', 
      valueType: 'boolean', // 布尔类型
      defaultValue: false,
    },
    {
      key: 'mode',
      label: '模式', 
      valueType: 'string',
      defaultValue: 'mode1',
     	dropdown: [ // 下拉属性
        { label: '模式一', value: 'mode1' },
        { label: '模式二', value: 'mode2' }
      ],
    },
    {
      key: 'backgroundColor',
      label: '按钮颜色',
      valueType: 'color', // 颜色类型
      defaultValue: '#1495ef',
    },
  ],
};

生成的积木如下:

""

字段解释:

属性解释
key控件的属性
label属性的显示名称,一般是中文
valueType属性的类型,当前支持'number'、'string'、'boolean'、color三种类型。
defaultValue属性的默认值,默认值要与 valueType 相对应,比如 valueType 为 boolean 时,defaultValue 应该为 false 或者 true。
dropdown选填,如果属性的值为特定的几个值时,可以使用 dropdown,避免手动输入。

TIP

__width、__height为可见控件内置属性,当控件拖到舞台时,控件默认的宽高为 __widget、__height 属性对应的 defaultValue值。

内置属性名属性类型属性作用示例值说明
__disabledboolean未知true
__widthnumber控件宽度80
__heightnumber控件高度160
__sizenumber未知100
__opacitynumber控件透明度50需自行设置 validators,使用示例值即可

控件方法(methods)

代码如下,有删减:

js
const types = {
  methods: [
   {
      key: 'blink',
      label: '开始闪烁',
      params: [
        {
          key: 'times',
          label: '次数',
          valueType: 'number',
          defaultValue: 5,
        },
      ],
    },
    {
      key: 'getClickCount',
      label: '获取点击次数',
      params: [],
      valueType: 'number', // 方法有返回值
    },
  ],
};

生成的积木如下: ""

字段解释:

属性解释
key方法名
label方法的显示名称,一般为中文
params方法的参数列表
params.key参数名,命名规则:英文 + 数字组成,不能以数字开头
params.label参数的显示名称,一般为中文
params.valueType参数的类型,当前支持'number'、'string'、'boolean'三种类型
params.dropdown选填,如果参数的值为特定的几个值时,可以使用 dropdown,避免手动输入。
valueType选填,当方法有返回值时设置 valueType

控件事件(events)

代码如下,有删减:

js
const types = {
  events: [
    {
      key: 'onClick',
      label: '被点击',
      params: [
        {
          key: 'content',
          label: '按钮文案',
          valueType: 'string',
        },
      ]
    }
  ]
};

生成的积木如下: ""

字段解释:

属性解释
key事件名
命名规范:英文 + 数字组成,不能以数字开头
label事件显示名称,一般为中文
params事件的参数列表
params.key参数名,命名规则:英文 + 数字组成,不能以数字开头
params.label参数的显示名称,一般为中文
params.valueType参数的类型,当前支持'number'、'string'、'boolean'三种类型

控件实体定义

控件实体是一个继承 InvisibleWidget 或者 VisibleWidget 的类,其中包含初始化、方法定义、事件触发、渲染(仅可见控件)等。

在运行时,会根据控件的属性值初始化一个实例对象。

js
class BlinkButtonWidget extends VisibleWidget {
  // 初始化
  constructor(props) {
    super(props);
    this.content = props.content;
    this.disabled = props.disabled;
    this.mode = props.mode;
    this.backgroundColor = props.backgroundColor;
    this.clickCount = 0;
  }

  // 方法定义,用于事件处理
  onClick = () => {
    this.emit('onClick', this.content);
    this.clickCount++;
  };

  // 方法定义
  blink = (times) => {
    // 开始闪烁
    for (let i = 0; i < times; i++) {
      setTimeout(() => {
        this.setProps({
          backgroundColor: getRandomColor(),
        });
      }, i * 100);
    }
  };

  getClickCount = () => {
    return this.clickCount;
  };

  // 渲染函数
  render() {
    return (
      <button
        onClick={this.onClick}
        disabled={this.disabled}
        style={{
          background: this.disabled ? '#ccc' : this.backgroundColor,
          borderRadius: this.mode === 'mode1' ? 5 : 0,
          fontWeight: this.mode === 'mode1' ? 'bold' : 'normal',
          width: '100%',
          height: '100%',
          border: 'none',
          color: '#fff',
        }}>
        {this.content}
      </button>
    );
  }
}

初始化

将控件的属性通过 props 传入,这里的 props 其实就是控件类型定义中的 properties 中的属性,包含 __width(内置)、__height(内置)、content、disabled、mode等属性。

TIP

__width、__height为内置属性,非必要情况下,在自定义控件中不建议使用内置属性。

js
class BlinkButtonWidget extends VisibleWidget {
 	constructor(props) {
  	super(props);
  	this.content = props.content;
    this.disabled = props.disabled;
    this.mode = props.mode;
    this.backgroundColor = props.backgroundColor;
    this.clickCount = 0;
	}
}

方法定义

在控件类型定义中,定义了两个方法,blink 和 getClickCount,对应的我们需要在控件实体中定义同名的两个方法,方法的参数类型和数量也需要一致,如下:

js
class BlinkButtonWidget extends VisibleWidget {
 	// 方法定义
  blink = (times) => {
    // 开始闪烁
    for (let i = 0; i < times; i++) {
      setTimeout(() => {
        this.setProps({
          backgroundColor: getRandomColor(),
        });
      }, i * 100);
    }
  };

  // 获取按钮点击次数
  getClickCount = () => {
    return this.clickCount;
  };
}

当执行以下两个积木时,会调用上边定义的 blink 和 getClickCount 方法。

事件触发

事件触发有很多场景,比如按钮被点击时、发送请求获取天气成功时、输入框失去焦点等等 在控件实体中,可以通过父级类提供的 emit方法触发指定的事件,格式为 this.emit('eventName', param1, param2, ...),可以不传入参数,也可以传入一个或多个参数。比如:

js
this.emit('onClick', content);
this.emit('onGetApiSuccess', code, data);
this.emit('onInputBlur');

如果通过积木注册监听了闪烁按钮的点击事件

当在控件实体中调用 this.emit('onClick', '提交')时,以上积木将会执行,并且参数积木按钮文案的值为 提交。

渲染方法(render)

js
class BlinkButtonWidget extends VisibleWidget {
  // 渲染方法
  render() {
    return (
      <button
        onClick={this.onClick}
        disabled={this.disabled}
        style={{
          background: this.disabled ? '#ccc' : this.backgroundColor,
          borderRadius: this.mode === 'mode1' ? 5 : 0,
          fontWeight: this.mode === 'mode1' ? 'bold' : 'normal',
          width: '100%',
          height: '100%',
          border: 'none',
          color: '#fff',
        }}>
        {this.content}
      </button>
    );
  }
}

可见控件需要定义 render 函数,用于在屏幕(舞台)上生成 UI 界面,这里使用了 JSX 语法。 有的 UI 元素需要响应用户的操作,比如鼠标点击、键盘输入等,通过在元素指定 onClick、onKeyDown 等的处理函数,在函数中触发事件,即可执行响应的逻辑。

TIP

不可见控件不需要定义 render 函数

控件导出

在控件类型定义和控件实体定义都编写完成后,你需要用exports语句来导出你的控件:

js
exports.types = types
exports.widget = BlinkButtonWidget

替换=后面的types为类型定义名,widget为实体定义类名。

两种控件区别

1、基础字段isInvisibleWidget 的值不同

可见控件 isInvisibleWidget: false

不可见控件isInvisibleWidget: true

2、文件格式

可见控件.jsx

不可见控件.js

3、继承的类不同

可见控件继承 VisibleWidget

不可见控件继承 InvisibleWidget

4、定义 render 方法

可见控件必须定义 render 方法,通过该方法渲染指定的内容到屏幕上;

不可见控件因为不需要渲染,不需要提供 render 方法。

5、设置属性的方式

不可见控件不需要渲染,设置属性的方式比较简单,直接 this.value = newValue 即可;

可见控件设置属性,需要显式地调用 setProps 方法,比如 this.setProps({ 'value': newVale }),该方法调用完成后,会自动渲染一次。