从小程序基础库版本 1.6.3 开始,小程序支持简洁的组件化编程。所有自定义组件相关特性都需要基础库版本 1.6.3 或更高。组件化编程的精髓是高内聚低耦合的复用机制,这对任意一家平台开发商而言都是降低成本和保证高质量运营的关键。

小程序组件化编程有什么特点
◐ 封装粒度小于页面,是特定业务面(Business Aspects)的封装器
一个自定义组件由 json wxml wxss js 4个文件组成,分别代表声明、模板、样式和逻辑,这点和页面相同,组件声明的格式如下:
json文件
{
"component": true
}
wxml文件
<!-- 这是自定义组件的内部 WXML 结构 -->
<view class="inner">
{{innerText}}
</view>
<slot></slot>
vue玩家这里很熟悉吧,有一个分发槽,干什么的我就不用说了[大笑]
wxss文件
/* 这里的样式只应用于这个自定义组件 */
.inner {
color: red;
}
js文件
//构造器
Component({
properties: {
// 这里定义了 innerText 属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
}
},
// 私有数据,可用于模板渲染
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod: function(){}
},
//公用的代码段,面向面的编程,比如加载、销毁时的log等
behaviors: [],
//组件生命周期
lifetimes:{
},
//组件所在页面生命周期
pageLifetimes:{
}
})
引用组件时,需在引用页面或组件的json文件中声明
{
"usingComponents": {
"component-tag-name": "path/to/the/custom/component"
}
}
usingComponents会触发Components构造器的调用,因此,我们如果把页面也作为特殊的组件,则可以通过引入usingComponents和Components的方式使页面组件化,这样会潜在的带来很多好处,比如:如访问页面 /pages/index/index?paramA=123¶mB=xyz ,如果声明有属性 paramA 或 paramB ,则它们会被赋值为 123 或 xyz,如此等等吧。
◐ 组件属性、数据的使用和通讯
组件化方法是自治策略的应用,因此,组件机制应解决数据传入、自身渲染和上下文数据通讯的问题,在微信小程序里,其分别的实现机制如下:
【1】数据传递和Vue机制类似,父传子通过properties,子传父通过子组件触发事件来完成,触发事件须使用triggerEvent 方法,指定事件名、detail对象和事件选项,如下例:
Component({
properties: {},
methods: {
onTap: function(){
var myEventDetail = {} // detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
})
除了上述两种情况,还有父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法,爱怎么玩怎么玩。但这里要注意,调用时需要传入一个匹配选择器 selector,如:this.selectComponent(".my-component")。
【2】组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发。其中,最重要的周期事件是 created、attached、detached ,包含一个组件实例生命流程的最主要时间点。组件的生命周期对应事件写在组件构造器的lifetimes对象里。
Component({
lifetimes: {
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
},
// 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
// ...
})
组件关联页面的跟踪和监控写在pageLifetimes里。
Component({
pageLifetimes: {
show: function() {
// 页面被展示
},
hide: function() {
// 页面被隐藏
},
resize: function(size) {
// 页面尺寸变化
}
}
})
组件的数据监听机制
组件通过 observers对象提供vue中类似watch的功能以实现数据监听,在MVVM模型中,数据的变化驱动事件产生必须有数据监听机制才行,这里不废话了,上个例子。
Component({
observers: {
'some.subfield': function(subfield) {
// 使用 setData 设置 this.data.some.subfield 时触发
// (除此以外,使用 setData 设置 this.data.some 也会触发)
subfield === this.data.some.subfield
},
'arr[12]': function(arr12) {
// 使用 setData 设置 this.data.arr[12] 时触发
// (除此以外,使用 setData 设置 this.data.arr 也会触发)
arr12 === this.data.arr[12]
},
'numberA, numberB': function(numberA, numberB) {
// 在 numberA 或者 numberB 被设置时,执行这个函数
this.setData({
sum: numberA + numberB
})
}
}
})
小程序开发的最佳实践
◐ 模块化
可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。
// common.js
function sayHello(name) {
console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
console.log(`Goodbye ${name} !`)
}
module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye
在需要使用这些模块的文件中,使用 require 将公共代码引入
var common = require('common.js')
Page({
helloMINA: function() {
common.sayHello('MINA')
},
goodbyeMINA: function() {
common.sayGoodbye('MINA')
}
})
◐ 避免异常
出现 JavaScript 异常、网络异常可能导致程序的交互无法进行下去,我们应当追求异常对正常交互的干扰,保证程序的高鲁棒性和高可用性。
◐ 不使用废弃接口
使用即将废弃或已废弃接口,可能导致小程序运行不正常。一般而言,接口不会立即去掉,但保险起见,建议不要使用,避免后续小程序突然运行异常。不要使用任何文档中提示废弃的接口。
◐ 避免setData数据冗余
setData操作会引起框架处理一些渲染界面相关的工作,一个未绑定的变量意味着与界面渲染无关,传入setData会造成不必要的性能消耗。因此,setData传入的所有数据在模板渲染中都要有相关依赖。
◐ 最低基础库版本
当使用的组件/API 的支持版本大于配置的线上最低基础库版本时,可能导致相应功能不可用。开发者可通过调整最低基础库版本或在代码上兼容的方式解决该问题。不要存在使用的组件/API 的支持版本大于配置的线上最低基础库版本的情况。
◐ 移除不可访问到的页面
小程序的包大小会影响加载时间,应该尽量控制包体积大小,避免将不会被使用的文件打包进去。存在访问不到的页面被打包到小程序中
◐ 及时回收定时器
定时器是全局的,并不是跟页面绑定的,当小程序从一个页面路由到另一个页面之后,前一个页面定时器应注意手动回收。因此,确保所有定时器的回调执行时,所在的页面都与设置定时器的页面一致。
结合前面一片的小程序开发,现在相信马上可以开始干活了,小程序是一个相对完整的封闭开发环境,和VUE、HBuilderX的uni-app等还是存在差异的,使用时多摸索多学习,相信一定会开发出令人眼前一亮的小程序。最后,还是那句话,打赏打赏。

#头条创作挑战赛#