微信小程序提倡以简单的开发方式打造轻量级应用,但小程序需求量越来越大,业务需求往往难以梳理,对开发方式提出了更高的要求,组件化开发是协同合作、提高开发效率的关键。
小程序本身的组件能力也在逐渐完善,从最开始只有官方的基础组件定制性较低,到从 1.6.3 开始支持自定义组件,进而开放插件功能。本文将探索一些小程序自定义组件的解决方案。先从一个非常简单的提示弹窗组件开始,效果图如下:
在小程序 1.6.3 版本之前,你只能提取组件的 *.wxml、*.js、*.wxss 文件,自行打包,然后通过以下两种方式将组件引入到页面中:
使用导入模板
即模板、小程序文件定义:
WXML 提供了模板(),可以在其中定义代码片段,然后从不同的地方调用。
我们将组件放在具有以下结构的目录中:
components/
└─toast/
├─toast.js
├─toast.wxml
└─toast.wxss
该组件不需要配置文件*.json,其余部分与小程序页面相同,由*.wxml、*.js、*.wxss文件组成。
在.wxml文件中定义组件模板,并使用name属性作为模板的名称:
name="toast">
class="{{iconType}}">
{{toastMsg}}
样式文件的编写方式与普通页面一致,组件的方法、事件、构造函数都需要在.js中定义并导出。
组件的使用
使用组件时,首先将组件引入页面,然后指定is属性为模板的名称,再将页面数据通过data属性传递到模板中(注意使用了扩展操作符...来展开对象)。
src="toast.wxml" />
is="toast" data="{{...toastData}}">
组件样式在页面的样式文件中通过@“.wxss”引入,如果使用组件的方式,需要在js中引入并初始化组件。
方式
关于 和 的区别,小程序文档有描述:
在这个文件中可以使用目标文件定义,可以导入目标文件除目标文件之外的全部代码,相当于复制到该位置,模板有自己的作用域,只能使用data传入的数据。
该模式很简单,就是简单的代码替换,没有作用域,不能像模板一样使用数据属性传递数据,只能通过将当前页面的数据对象传递给组件来绑定数据并渲染页面。
组件依然是由*.wxml、*.js、*.wxss文件组成,*.wxml、*.wxss的写法和普通页面一样,组件js也需要封装组件方法和事件、导出构造函数,使用组件时只要在页面中添加src=".wxml"/>即可复制组件模板。
无论怎样构造组件,最大的难点在于如何封装组件的构造函数,并暴露出属性和方法。之前采用的方法是调用()方法获取当前页面对象,再使用.()将组件的事件和方法“合并”到页面对象中,但这并没有解决组件事件传递、作用域隔离等一系列问题。因此,在小程序自定义组件能力开放之前,组件化可以说是相当尴尬的。对于复杂的组件,写起来真的是很痛苦!!终于从基础库1.6.3版本开始,小程序支持简单的组件化编程。
官方定制组件
自定义组件的官方文档非常全面,规范了小程序组件的开发。它描述了:
开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中复用;也可以将复杂的页面拆分成多个低耦合的模块,方便代码维护。自定义组件的使用方式与基础组件非常相似。
有了自定义组件之后,写组件就简单多了,我们还是以前那个组件为例,目录结构为:
components/
└─toast/
├─toast.js
├─toast.wxml
├─toast.wxss
└─toast.json
组件目录比上一种方法多了一个.json文件,我们需要在这个json配置文件中将字段声明为true,来表示自定义组件:
{
"component": true
}
组件模板、样式的编写和常规页面类似,那么上面最蛋疼的组件封装在自定义组件中是如何实现的呢?.js 中有一个组件构造函数,通过构造函数来注册组件,并提供组件的属性定义、内部数据以及自定义方法,例如:
// toast.js
Component({
properties: {
toastMsg: { // 属性名
type: String, // 类型(必填)
value: '', // 属性初始值(可选),可以在组件使用时指定
}
},
data: {
// 组件内部数据
isToastShow: false
},
methods: {
// 组件的自定义方法
toastShow: function () {
this.setData({
isToastShow: true
});
}
}
})
构造函数中支持的内容如下表所示:
自定义组件的使用
组件的使用很简单,首先在页面的json文件中做引用声明:
"usingComponents": {
"toast": "/components/toast/toast"
}
现在,您可以直接使用带有组件名称的标签将其导入页面,并将属性值传递给组件,而无需再来回走动。
id="toast" icon-type="okay" toast-msg="okay成功啦">
在页面的生命周期函数()中获取组件实例,就可以愉快的使用组件的方法了。
onLoad: function () {
// 获得toast组件
this.toast = this.selectComponent("#toast");
this.toast.toastShow()
}
从事件方面来说,监听自定义组件事件的方法与监听基本组件事件的方法完全相同。
bindmyevent="onMyEvent" />
bind:myevent="onMyEvent" />
在实际应用中发现,第二种方法bind:的兼容性更好。
当自定义组件触发事件时,需要使用方法指定事件名称、对象和事件选项:
bindtap="onTap">点击这个按钮将触发“myevent”事件
Component({
properties: {}
methods: {
onMyEvent: function(e){
e.detail // 自定义组件触发事件时提供的detail对象
},
onTap: function () {
var myEventDetail = {} // detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
})
自定义组件也有很多丰富的功能,比如像 Vue.js 中引入插槽的概念,用于携带组件引用时提供的子节点;利用小程序提供的数据进行组件间通信等等。总的来说,自定义组件推出之后,组件编程变得更加便捷和规范。在小程序组件化的探索中,第三方组件化框架也层出不穷。
第三方组件框架
下面介绍两个将小程序开发模式转化为MVVM的优秀框架:
我们
WePY 是一个支持组件化开发小程序的框架,预编译的方式可以让开发者选择自己喜欢的开发风格来开发小程序,采用类 Vue 开发风格,单文件模式,支持 Less/Sass/、/ 等多种编译器,可以大大提高开发效率。
WePY 采用类似 Vue.js 的开发风格,是一个使用 Vue.js 开发小程序的前端框架,直接将 Vue 应用转化为小程序,可以说是完整的 Vue.js 开发体验,同时支持 Vuex 数据管理方案和构建机制,令人兴奋的是,它还具备将 H5 代码转化为小程序目标代码的功能。
概括
以上这些小程序组件方案,我们该如何选择呢?从组件功能上来说,WePY 和 是比较完美的。如果从整体上衡量,使用前需要先熟悉 Vue.js,开发时也需要实时编译后再进行调试。该框架更适合在大型项目中使用。
对于中小型项目,当只需要展示组件,且没有动态变化的数据时,可以使用直接复制;当组件需要根据数据进行渲染时,可以通过数据属性传递数据。当组件比较复杂,涉及到事件、方法调用时,可以使用自定义组件。
此外,小程序基础库1.9.6版本开始支持插件功能,开发者可以像开发小程序一样编写插件并上传代码,插件发布后供其他小程序调用。如何利用组件化提高开发效率和用户体验值得我们不断思考,期待小程序的组件化能力越来越强大。