跳到主要内容
自定义组件
CabinX对外允许用户通过系统组件再次组合创建自定义组件,整体规则和创建页面十分相似。对内可以使用原生标签定制个性化组件。

对外CabinX提供了XComponent()用于自定义组件,该函数自定义组件中依然不能使用原生Html标签,仅支持组合已提供的组件生成自定义组件。

XComponent()无法满足需求,需要定制更具个性化的自定义组件时,可以使用SysComponent()自定义组件,该函数创建的自定义组件支持使用原生标签,但需要向CabinX团队申请权限,一般来说仅建议专业前端同学使用,申请方式请查看文档SysComponent开发者权限申请手册

创建

创建新组件时,在项目中任何目录下创建文件夹,用于放置同名 js 文件和 dml 文件:

myproject
└── dev
└── myproject
└── pages

└── newpage
├── newpage.dml
├── newpage.js
└── mycomponent
├── mycomponent.dml
└── mycomponent.js

dml 中根节点可以是系统任意组件,一个 dml 文件中只能有一个根节点

<module title="module-{{ title }}" subtitle="通常一些重复使用的功能模块需要创建组件">
<form>
<item node="input" label="姓名" name="key1"/>
<item node="input" label="年龄" name="key2"/>
</form>
</module>

js 文件中通过 XComponents() 方法注册一个CabinX自定义组件,入参是个对象,包含data以及生命周期方法:

export default XComponent( {
API : [ 'myShow', 'myHide' ], // 需要对外部暴露的API方法,不支持属性,通过getComponent方法获取对象调用
props : ['title'], // 从外部传入的参数
data : {}, // 和page一样,组件内部数据
hooks: { // 生命周期函数
show: function() {}, // 组件挂载后执行
hide: function() {}, // 组件销毁时执行
},
myShow : function() {}, // 对外暴露的方法,必须在API中进行声明
myHide : function() {} // 对外暴露的方法,必须在API中进行声明
} );

调用

自定义组件被调用时需要在 XPageXComponent 中进行注册,注册后可以在 dml 中直接使用标签,以上文页面为例

newpage.dml

<page>
<!-- title属性是组件props中已声明的属性 -->
<mycomponent-nickname title="调用者传入的标题"/>
</page>

newpage.js

import mycomponent form './mycomponent/mycomponent'
export default XPage({
// 通过components属性注册组件在当前页面或组件中使用
components : {
'mycomponent-nickname' : mycomponent
}
});

组件通信及事件

组件间的基本通信方式有一下几种:

  • DML数据绑定:用于父组件向子组件属性传递数据。
  • API:父组件通过 this.getComponent 获取组件实例对象,直接调用已注册API。
  • 事件:用于子组件向父组件传递数据。

本小节重点介绍API和事件。

API

组件内自定义方法可以通过注册 API 供外界调用

page.dml:

<page>
<actions>
<button text="调用组件事件" bindclick="applyFunction"/>
</actions>
<mycomponent-nickname x="mycomponent"/>
</page>

page.js:

import mycomponent form './mycomponent/mycomponent'
export default XPage({
// 通过components属性注册组件在当前页面或组件中标签名
components : {
'mycomponent-nickname' : mycomponent
},
applyFunction : function() {
// 注册的组件默认有x属性
this.getComponent( 'mycomponent' ).changeData();
}
});

components.dml:

<module title="{{ title }}" height="200px">
</module>

components.js:

export default XComponent( {
API : ['changeData'],
data : {
title : 'module name'
}
changeData : function() {
this.setData( { title : 'new name' } );
}
} );

事件

在组件内部任何时候可以通过 triggerEvent( eventName, Object ) 向父组件传递数据:

page.dml:

<page>
<actions>
<button text="调用组件事件" bindclick="applyFunction"/>
</actions>
<!-- 绑定自定义事件 onchangedata -->
<mycomponent-nickname x="mycomponent" bindonchangedata="logInfo"/>
</page>

page.js:

import mycomponent form './mycomponent/mycomponent'
export default XPage({
// 通过components属性注册组件在当前页面或组件中标签名
components : {
'mycomponent-nickname' : mycomponent
},
applyFunction : function() {
// 注册的组件默认有x属性
this.getComponent( 'mycomponent' ).changeData();
},
logoInfo : function() {

}
});

components.dml:

<module title="{{ title }}" subtitle="{{ subtitle }}"height="200px">
</module>

components.js:

export default XComponent({
API: ['changeData'],
props: {
initialTitle: {
type: String,
default: '默认 title',
},
subtitle: {},
},

data: {
title: '',
},

hooks: {
show() {
const { initialTitle } = this.props;

this.initTitle(initialTitle);
},

hide() {},
},

initTitle(title) {
this.setData({ title });
},

changeData: function (newTitle) {
this.initTitle(newTitle);

// 这里触发的事件就是page.dml中绑定的事件
this.triggerEvent('onchangedata', {
name: 'myEvent',
});
},

watch: {
initialTitle(value) {
this.initTitle(value);
},
}
});