对外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中进行声明
} );
调用
自定义组件被调用时需要在 XPage
或 XComponent
中进行注册,注册后可以在 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);
},
}
});