自定义组件从小程序基础库版本 1.6.3 开始,小程序支持简洁的组件化编程。开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似。
前言
从去年开始接触了vue以后,就一发不可收拾,尤其是vue的一切皆组件的思想,通过数据的分离,将各功能模块组件化,也将代码再次解耦,写代码的效率提高了,思路也更清晰了,到了2017年,开始负责公司的小程序开发,在踩了无数的坑以后,也接连发布了两个项目,小程序也引用了vue的思路,数据绑定,页面模块分离,但是又不像vue那样能够自由的分离拆解各个组件,终于,就在半个月前,小程序开始了自定义组件的公测,我也在开发的新项目中第一时间引入了自定义组件,和以前一样,看着超级减配摸索版的官方文档,开始了小程序的又一个填坑之旅。
开始组件化
众所周知,小程序的页面都是采用了模块化的管理方式,每个页面都对应着四个文件,分别负责结构,逻辑,样式和基础配置,同样,自定义组件也保持着这样的结构,一个自定义组件由wxml,wxss,js,json,4个文件组成,如果想要在页面中引入相应的组件,首先,需要在该页面的json文件里写入一下配置:
{
"component": true,
"usingComponents": {
"component-Name": "Path",
......
}
}
同样,如果组件也是由更加细分的组件组成的话,配置是一样的,对应的,在上层的wxml里直接以标签的形式载入组件:
<component-Name></component-Name>
这样,一个自定义的组件就完成了,这个标签对应的内容就是该组件,以下面的这个页面为例:
image.png产品展示的区域都是由组件构成的,分为三个组件,展示区域 > 标题 > 列表,列表还可以继续再分为两个组件,列表 > 列表内容,对于这种高复用性的内容,组件化可以极大的减少代码量和优化代码结构,例如,点开更多后的页面,就可以复用 列表 + 列表内容的组件,如果产品下方的区域还有动态展示,成交记录等等,都可以复用以上组件,但是,组件之间的数据传递时怎么进行的呢?
组件数据的传递
组件之间的数据传递分为很多种,例如,在上级组件传递数据、事件给下级页面,上级页面监听下级页面的事件回调,跨级的数据传递,例如,在首页将获取的产品列表数据传递给产品列表组件:
上级组件:
<component-list list-data="{{ListData}}"></component-list>
下级组件:
wxml:
<view wx:for="{{ListData}}">
<view class="item">{{item.data}}</view>
......
</view>
js:
Component({
properties: {
ListData: {
type: Array,
value: [],
observer: function(newData, oldData){
......
}
}
},
data: {
someData: {}
},
methods: {
customMethod: function(){}
}
})
可以看到,组件的写法和页面基本一样,只是Page变成了Component,这里要注意,只要是由上层组件传递过来的数据,都应该在properties里声明,数据类型是必须值,而observer则是监听数据变化后产生的事件,例如,上级页面的传递的值产生变化了,就可以在observer里捕获到两个值newData, oldData,在observer里可以调用该组件的methods,去做不同的操作。同样,组件也有生命周期,这点和page略有区别,文档里对这一点写的还是很详细的。可是,如果遇到跨组件的数据该怎么传递呢?
根据官方的说法,组件的事件是逐层传递的,并没有广播机制,这样的话就有些麻烦了,以上图为例,如果主页想要把数据传递给产品展示组件的列表组件的详情组件(有些绕),就要在每一层组件中都声明,然后把时间和数据进行逐层传递。
根据多组件数据传递的特性,可以将数据的标识,或者api向下传递,在组件中请求、渲染,这样对于复用率较高的组件来说比较便于管理,以此为例,home-show
为下层组件,home-show
里又包含了组件home-show-title
和home-list
,只用传入相应的标识,即可将不同的数据在不同的组件里请求和渲染:
<home-show showTitle="产品展示" more="product" detailApi="{{ProductDetailApi}}" showList="{{info.EntProductModelList}}"></home-show>
<list loadApi="{{api}}" root="{{root}}" detailApi="{{detailApi}}" isRefresh="{{isRefresh}}"></list>
<view class="show_container">
<home-show-title title="{{showTitle}}" more="{{more}}"></home-show-title>
<home-list list="{{showList}}" detailApi="{{detailApi}}" isNews="{{isNews}}"></home-list>
</view>
组件事件
根据官方文档,引用组件的页面可以监听到组件中触发的任意事件,如下写法:
<!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 -->
<component-tag-name bindmyevent="onMyEvent" />
可是在实际使用中发现,第一种方法貌似兼容性并不好,可以用如下的方式代替:
<component-tag-name bind:myevent="onMyEvent" />
在组件中触发事件时,可以使用triggerEvent
方法,这个在文档里写的还算是清楚,就直接照搬了:
<!-- 在自定义组件中 -->
<button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>
Component({
properties: {}
methods: {
onTap: function(){
var myEventDetail = {} // detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
})
behaviors
behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的“mixins”或“traits”。
每个 behavior 可以包含一组属性、数据、生命周期函数和方法,组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。每个组件可以引用多个 behavior 。 behavior 也可以引用其他 behavior 。
关于behaviors,刚刚接触的时候还是云里雾里,通过在实际的使用中发现,它其实就是把不同的组件中需要单独定义的内容提取出来,可以在组件的js文件开头引用,就像引用任何一个库或者文件一样,import *** from ***
,如果组件中有同名的属性或方法,会进行覆盖,后面的覆盖前面的,而数据则会进行合并,这点具体可参考文档字段的覆盖和组合规则
,有了behaviors
,自定义的组件的可能性又被延伸,可以根据业务需要进行不同的搭配
end
总的来说,微信开放了自定义组件,也再次开放了小程度,开发者可以更高效率和自由的进行开发,但是现在还在公测阶段,开发中要注意的问题还是挺多的,例如,通过组件里的wxss文件,可以定义组件的样式,但是自定义组件的样式还有一些规则,这点可以参考文档的组件模版和样式
;在引用组件页面的json文件里,如果添加了usingComponents
还会导致页面不正常,而且引用组件的路径也偶尔会不一致发生错误。。。
填坑持续进行中。。。
网友评论
ListData: {
type: Array,
value: [],
observer: function(newData, oldData){
......
}
}
上述讲的是通过这样的方式传值,为啥我打印这两个值newData,oldData这个值根本就没有输出?这个ListData的值有发生变化