背景先談下背景,在做一款產(chǎn)品的時(shí)候需要用到日期選擇器,但是官方的卻不太滿足需求,因?yàn)闊o(wú)法選擇農(nóng)歷啊。所以自己來(lái)造一個(gè)輪子好了,造輪子之前先想想啊,萬(wàn)一以后多個(gè)地方要用到,多個(gè)項(xiàng)目要用,怎么辦呢?那把這 ...
先談下背景,在做一款產(chǎn)品的時(shí)候需要用到日期選擇器,但是官方的卻不太滿足需求,因?yàn)闊o(wú)法選擇農(nóng)歷啊。所以自己來(lái)造一個(gè)輪子好了,造輪子之前先想想啊,萬(wàn)一以后多個(gè)地方要用到,多個(gè)項(xiàng)目要用,怎么辦呢?
那把這個(gè)輪子抽象,定義輸入輸出,即接口。組件里面怎么運(yùn)轉(zhuǎn)調(diào)用方不管啊,給了什么輸入,就只管結(jié)果好了。
組件的三要素就是小程序定義的三種文件:
因?yàn)閖s本身就是模塊化開發(fā),所以這天然有利于組件化。wxml和wxss呢,定義了組件的皮膚,小程序的模板template標(biāo)簽可以方便wxml的復(fù)用。至于wxss,沒有獨(dú)立出來(lái),目前沒發(fā)現(xiàn)要怎么整合到獨(dú)立的組件中去,而不與其他的wxss發(fā)生耦合。
<template name="myTemplate">
<view>
<text> {{index}}: {{msg}} text>
<text> Time: {{time}} text>
view>
template>
用法
// 如果模板是寫在單獨(dú)的wxml文件,則要inport,引入。路徑則是當(dāng)前文件的相對(duì)路徑。
<import src="../cal/calendar.wxml">import>
<template is="myTemplate" data="{{...item}}"/>
需要注意的是data數(shù)據(jù)是有單獨(dú)的作用域的,只能使用data傳入的數(shù)據(jù)。具體的理解就是:
data: {
item: {
index: int
msg: string
time: string
},
index: int
msg: string
time: string
}
模板里面的數(shù)據(jù)實(shí)際顯示的是item的屬性,而不是和item同級(jí)的屬性。
模板還有一種用法
<template is="myTemplate" data="{{index,msg,time}}"/>
這樣就要傳入模板中用到的三個(gè)變量,而不是item一個(gè)對(duì)象。模板渲染的結(jié)果則是最外層的index屬性,而不是item的index屬性值。
…符號(hào)是擴(kuò)展運(yùn)算符,理解為將一個(gè)對(duì)象所以的屬性展開傳遞給模板,這樣的好處是不要傳遞多個(gè),寫出的代碼更加簡(jiǎn)潔。擴(kuò)展運(yùn)算符是ES6的特性,有興趣可以深入學(xué)習(xí)。
如果運(yùn)用擴(kuò)展運(yùn)算符給模板傳入數(shù)據(jù),像上面怎么去更新單個(gè)key的值呢?小程序提供了可以根據(jù)屬性路徑更新的方法:
// 更新單個(gè)key,
this.setData({
index: 1
});
/* 更新對(duì)象中的單個(gè)key
item: {
index: int
msg: string
time: string
}
*/
this.setData({
'item.index': 1
});
// path必須是字符串,不能是變量替代。下面是不行的
path = 'item.index';
this.setData({
path: 1
});
雖然用法上是有點(diǎn)限制,但也避免了傳入一堆的參數(shù)給模板。
值得注意的是入?yún)ata的item必須是有初始化值,否則會(huì)報(bào)錯(cuò)。
所以利用template和js就可以打造一款組件了。先看下我所做的組件:
定義一個(gè)wxml文件
定義一個(gè)js文件
class Calendar {
...
}
日期類有自己的作用域名,所以組件內(nèi)部的事件導(dǎo)致數(shù)據(jù)更新的時(shí)候,還是要用頁(yè)面更新數(shù)據(jù)的方法this.setData,所以必須要將頁(yè)面對(duì)象傳遞給組件內(nèi)部。
頁(yè)面調(diào)用組件:
// this 是當(dāng)前頁(yè)面page對(duì)象,含有setData方法。
var calendar = new Calendar(this, function(date) {
that.setData({
date: date
})
});
// 當(dāng)選擇日期變化的時(shí)候,組件內(nèi)部事件: this.pageCtx 則是page上下文,即上面實(shí)例化組件入?yún)⒌膖his對(duì)象。
changeCalendarTab(e) {
this.pageCtx.setData({
'calendar_data.selectDateType':
+e.target.dataset.tap
});
this.data.selectDateType = +e.target.dataset.tap;
this.changeCallBack && this.changeCallBack(this.getCurrentSelectDate());
}
具體組件請(qǐng)參考我的github:calendar。
這樣就完成了一個(gè)組件編寫,任何需要用到的地方都可以引入了。小程序一個(gè)不太好的地方是沒有包管理的概念,導(dǎo)致跨項(xiàng)目見的公共模塊復(fù)用起來(lái)比較麻煩,下次進(jìn)行單獨(dú)講解。