微信小程序的特點(diǎn)
小程序是一種不需要下載、安裝即可使用的應(yīng)用,它出現(xiàn)了觸手可及的夢(mèng)想,用戶掃一掃或者搜一下即開打開應(yīng)用,也出現(xiàn)了用完即走的理念,用戶不用關(guān)心安裝太多應(yīng)用的問題,應(yīng)用隨處可用,但又無須安裝卸載。我當(dāng)時(shí)是這樣來定義什么是小程序的。
1:無需下載:我們直接使用它,所以無須安裝是小程序最基礎(chǔ)的一個(gè)特性;
2:觸手可及:當(dāng)我們拿著智能手機(jī)接觸周邊的時(shí)候,我們可以通過手機(jī)直接獲得信息,就是周邊的信息;
3:用完即走:對(duì)于周邊要完成的任務(wù)來說我們需要的是用完即走;
4:無須卸載:小程序看起來是程序,但是它以完全不同于過去APP的形狀出現(xiàn),它有更靈活的應(yīng)用組織形態(tài);
5:操作更接近原生App---可以實(shí)現(xiàn)一些打開攝像頭,錄像,上傳圖片、語音、支付等功能
微信小程序官方地址
官方工具:https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html?t=201714
簡(jiǎn)易教程:<https://mp.weixin.qq.com/debug/wxadoc/dev/
運(yùn)營(yíng)規(guī)范:https://mp.weixin.qq.com/debug/wxadoc/product/index.html;在這里查看禁止事項(xiàng);
接入指南:<https://mp.weixin.qq.com/debug/wxadoc/introduction/index.html
客服消息:https://mp.weixin.qq.com/debug/wxadoc/introduction/custom.html?t=20161221
支付文檔:<https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1
數(shù)據(jù)分析:<https://mp.weixin.qq.com/debug/wxadoc/analysis/index.html?t=201714
開發(fā)前必讀
必須通讀運(yùn)營(yíng)規(guī)范;有需要禁止開發(fā)的事項(xiàng)需要了解;
配置域名:必須配置域名后,才可以使用配置的域名,比如你需要請(qǐng)求XX地址的數(shù)據(jù),必須在后臺(tái)設(shè)置了域名之后,才可以真機(jī)請(qǐng)求數(shù)據(jù);必須https的域名才可以請(qǐng)求(本地測(cè)試時(shí)可以在小程序詳情中設(shè)置不校驗(yàn)合法域名功能)
小程序?qū)徍?/h4>
因小程序名稱,logo,簡(jiǎn)介等不符合要求被拒
功能頁面與所選的服務(wù)類目范圍不符
小程序功能流程不完整,功能過于簡(jiǎn)單
常見的審核拒絕情形:<https://mp.weixin.qq.com/debug/wxadoc/product/reject.html?t=201714
小程序架構(gòu)
-
主體部分主要由3個(gè)文件構(gòu)成
app.js:小程序邏輯,初始化APP
app.json :小程序配置,比如導(dǎo)航、窗口、頁面http請(qǐng)求跳轉(zhuǎn)等
app.wxss:公共樣式配置
因小程序名稱,logo,簡(jiǎn)介等不符合要求被拒
功能頁面與所選的服務(wù)類目范圍不符
小程序功能流程不完整,功能過于簡(jiǎn)單
常見的審核拒絕情形:<https://mp.weixin.qq.com/debug/wxadoc/product/reject.html?t=201714
主體部分主要由3個(gè)文件構(gòu)成
app.js:小程序邏輯,初始化APP
app.json :小程序配置,比如導(dǎo)航、窗口、頁面http請(qǐng)求跳轉(zhuǎn)等
app.wxss:公共樣式配置
主體配置完成之后,就是對(duì)應(yīng)的業(yè)務(wù)開發(fā)了,也就是開發(fā)者最常操作的頁面。小程序頁面設(shè)計(jì)基本上也是遵循 MVC 結(jié)構(gòu)進(jìn)行構(gòu)建。
MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設(shè)計(jì)典范,用一種業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,將業(yè)務(wù)邏輯聚集到一個(gè)部件里面,在改進(jìn)和個(gè)性化定制界面及用戶交互的同時(shí),不需要重新編寫業(yè)務(wù)邏輯。MVC被獨(dú)特的發(fā)展起來用于映射傳統(tǒng)的輸入、處理和輸出功能在一個(gè)邏輯的圖形化用戶界面的結(jié)構(gòu)中。
-
頁面由4個(gè)文件構(gòu)成
js:頁面邏輯,相當(dāng)于控制層(C);也包括部分的數(shù)據(jù)(M)
wxml:頁面結(jié)構(gòu)展示,相當(dāng)于視圖層(V)
wxss:頁面樣式表,純前端,用于輔助wxml展示
json:頁面配置,配置一些頁面展示的數(shù)據(jù),充當(dāng)部分的模型(M)

配置 app.json
全局配置頁面文件的路徑、窗口表現(xiàn)、設(shè)置網(wǎng)絡(luò)超時(shí)時(shí)間、設(shè)置多 tab 等
pages 接受一個(gè)數(shù)組,每一項(xiàng)都是字符串,來指定小程序由哪些頁面組成
window 用于設(shè)置小程序的狀態(tài)欄、導(dǎo)航條、標(biāo)題、窗口背景色。
tabBar
通過 tabBar 配置項(xiàng)指定 tab 欄的表現(xiàn),以及 tab 切換時(shí)顯示的對(duì)應(yīng)頁面。
tabBar 配置數(shù)組,只能配置最少2個(gè)、最多5個(gè) tab,tab 按數(shù)組的順序排序。
networkTimeout 可以設(shè)置各種網(wǎng)絡(luò)請(qǐng)求的超時(shí)時(shí)間。
debug
可以在開發(fā)者工具中開啟 debug 模式,在開發(fā)者工具的控制臺(tái)面板,調(diào)試信息以 info 的形式給出,其信息有Page的注冊(cè),頁面路由,數(shù)據(jù)更新,事件觸發(fā) 。 可以幫助開發(fā)者快速定位一些常見的問題。
page.json 每一個(gè)小程序頁面也可以使用.json文件來對(duì)本頁面的窗口表現(xiàn)進(jìn)行配置。 頁面的配置比app.json全局配置簡(jiǎn)單得多,只是設(shè)置 app.json 中的 window 配置項(xiàng)的內(nèi)容,頁面中配置項(xiàng)會(huì)覆蓋 app.json 的 window 中相同的配置項(xiàng)。
App()
用來注冊(cè)一個(gè)小程序。在小程序啟動(dòng)的時(shí)候調(diào)用,并創(chuàng)建小程序,直到銷毀。在整個(gè)小程序的生命周期過程中,它都是存在的。很顯然它是單例的,全局的。
- 只能在app.js中注冊(cè)一次。
- 在代碼的任何地方都可以通過 getApp() 獲取這個(gè)唯一的小程序單例,
App()的參數(shù)是 object 類型 {} ,指定了小程序的聲明周期函數(shù)。
globalData 對(duì)象
全局?jǐn)?shù)據(jù)。
let app = getApp();
let username= "username";
//設(shè)置全局變量
app.globalData.userInfo = {
username: username
};
let app = getApp();
let username= ""
//獲取全局變量
if (app.globalData.username) {
username= app.globalData.userInfo.username;
}
頁面生命周期和參數(shù)傳遞
初始頁面index.js啟動(dòng)會(huì)從app,js中的生命周期方法調(diào)用開始:onLaunch---onShow,然后開始調(diào)用index.js頁面中的生命周期方法:onLoad---onShow---onReady,當(dāng)點(diǎn)擊“后臺(tái)”時(shí),頁面index.js進(jìn)入后臺(tái),這時(shí)回調(diào)生命周期方法onHide,如果再點(diǎn)擊“前臺(tái)”,使頁面回到前臺(tái),這時(shí)回調(diào)頁面生命周期方法:onShow(注意,這時(shí)不再回調(diào)onLoad)
onLaunch 函數(shù)
監(jiān)聽小程序初始化。
當(dāng)小程序初始化完成時(shí),會(huì)觸發(fā) onLaunch(全局只觸發(fā)一次)。
onShow 函數(shù)
監(jiān)聽小程序顯示。
當(dāng)小程序啟動(dòng),或從后臺(tái)進(jìn)入前臺(tái)顯示,會(huì)觸發(fā)。
onHide 函數(shù)
監(jiān)聽小程序隱藏。
當(dāng)小程序從前臺(tái)進(jìn)入后臺(tái),會(huì)觸發(fā)。
所謂前后臺(tái)的定義,類似于手機(jī)上的app,比如當(dāng)不在使用微信時(shí),就進(jìn)入了后臺(tái)。
Page()
Page()的參數(shù)也是Object類型
onLoad
監(jiān)聽頁面加載
頁面剛開始加載的時(shí)候觸發(fā)。只會(huì)調(diào)用一次。
onReady 監(jiān)聽頁面初次渲染完成
類似于html的 onReady。只會(huì)調(diào)用一次。
onShow
監(jiān)聽頁面顯示
頁面顯示的時(shí)候觸發(fā),比如頁面切換
onHide
監(jiān)聽頁面隱藏
和onShow對(duì)應(yīng)
onUnload
監(jiān)聽頁面卸載
在 redirectTo 或 navigateBack 的時(shí)候調(diào)用
onPullDownRefresh
監(jiān)聽用戶下拉動(dòng)
1)需要在config的window選項(xiàng)中開啟enablePullDownRefresh。 2)當(dāng)處理完數(shù)據(jù)刷新后,wx.stopPullDownRefresh 可以停止當(dāng)前頁面的下拉刷新。
onReachBottom
頁面上拉觸底事件的處理函數(shù)
data
頁面的初始數(shù)據(jù)
Page.prototype.setData()
Page的函數(shù) setData() 用于頁面初始數(shù)據(jù)data的修改。如果該數(shù)據(jù)綁定到了視圖層wxml中展示,那么無須刷新,視圖層就會(huì)反映出修改。
對(duì)于data的修改,只能使用 setData() ,不能直接通過 this.data 進(jìn)行修改 。數(shù)據(jù)量限制在 1024 kb以內(nèi)。
通過this.data賦值的話,只對(duì)當(dāng)前方法生效,在其他方法與wxml中,不會(huì)生效。
getCurrentPages()
let pages = getCurrentPages();
let currPage = null; //當(dāng)前頁面
let prevPage = null; //上一個(gè)頁面
if (pages.length >= 2) {
currPage = pages[pages.length - 1]; //當(dāng)前頁面
prevPage = pages[pages.length - 2]; //上一個(gè)頁面
}
if(prevPage){
prevPage.setData({
dataFromB: '2018世界杯冠軍:'+this.data.array[e.detail.value]
});
}
頁面的跳轉(zhuǎn)
wx.navigateTo(Object object)
方法一:
在wxml中跳轉(zhuǎn)到detail頁面
<navigator url="detail?id={{item.id}}">
</navigator>
方法二:
在js中觸發(fā)事件跳轉(zhuǎn)到detail頁面
wx.navigateTo({
url: 'detail?id=1'
})
detail.js
Page({
onLoad: function(option){
console.log(option.query)
}
})
視圖層WXML
綁定數(shù)據(jù)、模板、邏輯
之前介紹了小程序的MVC結(jié)構(gòu):
- page.js 即控制層(C),也叫業(yè)務(wù)邏輯層;
- page.js 中的data屬性,即數(shù)據(jù)模型層(M);
- page.wxml 即展現(xiàn)層(V);
- page.wxss 即css,增強(qiáng)展現(xiàn)層效果(V);
通過業(yè)務(wù)邏輯層(C),修改data屬性(M),從而在展現(xiàn)層(V)中展示。即MVC設(shè)計(jì)模式。
如果在 data 中定義了某個(gè)變量,比如
Page({
data:{
title: '小程序分享',
desc: '視圖層—WXML'
}
})
wxml中取值
<view class="container">
<view class="title">{{title}}</view>
<view class="desc">{{desc}}</view>
</view>
效果:
數(shù)據(jù)綁定常用語法
內(nèi)容與組件屬性都需要在{{}}中
<view id="item-{{id}}">{{ message }}</view>
控制屬性
<view wx:if="{{condition}}"> </view>
關(guān)鍵字(需要{{ }}內(nèi))
<checkbox checked="{{false}}"> </checkbox>
注意:不要直接寫 checked="false",其計(jì)算結(jié)果是一個(gè)字符串,轉(zhuǎn)成 boolean 類型后代表真值。
三元運(yùn)算
<view hidden="{{flag ? true : false}}"> Hidden </view>
算數(shù)運(yùn)算
<view> {{a + b}} + {{c}} + d </view>
字符串運(yùn)算
<view>{{"hello" + name}}</view></pre>
列表渲染
wx:for
在組件上使用 wx:for 控制屬性綁定一個(gè)數(shù)組,即可使用數(shù)組中各項(xiàng)的數(shù)據(jù)重復(fù)渲染該組件。
默認(rèn)數(shù)組的當(dāng)前項(xiàng)的下標(biāo)變量名默認(rèn)為 index,數(shù)組當(dāng)前項(xiàng)的變量名默認(rèn)為 item
<view wx:for="{{array}}">
{{index}}: {{item.message}}
</view>
Page({
data: {
array: [{
message: 'foo',
}, {
message: 'bar'
}]
}
})
使用 wx:for-item 可以指定數(shù)組當(dāng)前元素的變量名,
使用 wx:for-index 可以指定數(shù)組當(dāng)前下標(biāo)的變量名:
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName.message}}
</view>
wx:for 也可以嵌套,下邊是一個(gè)九九乘法表
<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i">
<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j">
<view wx:if="{{i <= j}}">
{{i}} * {{j}} = {{i * j}}
</view>
</view>
</view>
block wx:for
類似 block wx:if,也可以將 wx:for 用在<block/>標(biāo)簽上,以渲染一個(gè)包含多節(jié)點(diǎn)的結(jié)構(gòu)塊。例如:
<block wx:for="{{[1, 2, 3]}}">
<view> {{index}}: </view>
<view> {{item}} </view>
</block>
WXSS
WXSS(WeiXin Style Sheets)是一套樣式語言,用于描述 WXML 的組件樣式。
WXSS 用來決定 WXML 的組件應(yīng)該怎么顯示。
為了適應(yīng)廣大的前端開發(fā)者,WXSS 具有 CSS 大部分特性。同時(shí)為了更適合開發(fā)微信小程序,WXSS 對(duì) CSS 進(jìn)行了擴(kuò)充以及修改。
與 CSS 相比,WXSS 擴(kuò)展的特性有:
尺寸單位
-
樣式導(dǎo)入
rpx(responsive pixel): 可以根據(jù)屏幕寬度進(jìn)行自適應(yīng)。規(guī)定屏幕寬為750rpx。如在 iPhone6 上,屏幕寬度為375px,共有750個(gè)物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
<figure class="md-table-fig" contenteditable="false" cid="n209" mdtype="table" style="box-sizing: border-box; margin: 1.2em 0px; overflow-x: auto; max-width: calc(100% + 16px); padding: 0px; cursor: default;">
設(shè)備 rpx換算px (屏幕寬度/750) px換算rpx (750/屏幕寬度) iPhone5 1rpx = 0.42px 1px = 2.34rpx iPhone6 1rpx = 0.5px 1px = 2rpx iPhone6 Plus 1rpx = 0.552px 1px = 1.81rpx </figure>
建議: 開發(fā)微信小程序時(shí)設(shè)計(jì)師可以用 iPhone6 作為視覺稿的標(biāo)準(zhǔn)。
注意: 在較小的屏幕上不可避免的會(huì)有一些毛刺,請(qǐng)?jiān)陂_發(fā)時(shí)盡量避免這種情況。
樣式導(dǎo)入
使用
@import語句可以導(dǎo)入外聯(lián)樣式表,@import后跟需要導(dǎo)入的外聯(lián)樣式表的相對(duì)路徑,用;表示語句結(jié)束。
事件
數(shù)據(jù)綁定、模板、邏輯等,主要的作用是在視圖中展示數(shù)據(jù),以及如何展示。但是只有展示是不夠的,我們需要互動(dòng)。比如一個(gè)HTML頁面,可以展示文字、圖片,但是還要有一些互動(dòng),比如鏈接、按鈕等?;?dòng)其實(shí)就是事件了。比如HTML中 button 的 onClick ,就是點(diǎn)擊的時(shí)候,觸發(fā)的動(dòng)作以及開發(fā)人員相應(yīng)的業(yè)務(wù)邏輯處理。
事件小例:bindtap
index.wxml:
<button bindtap="toEvent">視圖層WXML:事件</button></pre>
index.js:
toEvent : function(){
// 跳轉(zhuǎn)到 event.wxml頁面
wx.navigateTo({
url: '/pages/wxml/event'
})
}
事件分類
冒泡事件:當(dāng)一個(gè)組件上的事件被觸發(fā)后,該事件會(huì)向父節(jié)點(diǎn)傳遞。
非冒泡事件:當(dāng)一個(gè)組件上的事件被觸發(fā)后,該事件不會(huì)向父節(jié)點(diǎn)傳遞。
WXML的冒泡事件列表:
| 類型 | 觸發(fā)條件 |
|---|---|
| touchstart | 手指觸摸動(dòng)作開始 |
| touchmove | 手指觸摸后移動(dòng) |
| touchcancel | 手指觸摸動(dòng)作被打斷,如來電提醒,彈窗 |
| touchend | 手指觸摸動(dòng)作結(jié)束 |
| tap | 手指觸摸后馬上離開(最常用的事件,類似于click事件) |
| longpress | 手指觸摸后,超過350ms再離開,如果指定了事件回調(diào)函數(shù)并觸發(fā)了這個(gè) |
| longtap | 手指觸摸后,超過350ms再離開(推薦使用longpress事件代替) |
| transitionend | 會(huì)在 WXSS transition 或 wx.createAnimation 動(dòng)畫結(jié)束后觸發(fā) |
| animationstart | 會(huì)在一個(gè) WXSS animation 動(dòng)畫開始時(shí)觸發(fā) |
| animationiteration | 會(huì)在一個(gè) WXSS animation 一次迭代結(jié)束時(shí)觸發(fā) |
| animationend | 會(huì)在一個(gè) WXSS animation 動(dòng)畫完成時(shí)觸發(fā) |
| touchforcechange | 在支持 3D Touch 的 iPhone 設(shè)備,重按時(shí)會(huì)觸發(fā) |
事件以bind或者catch開頭
bind事件綁定不會(huì)阻止冒泡事件向上冒泡,如bindtap。
catch事件綁定可以阻止冒泡事件向上冒泡,如catchtap。
例:
<view id="outer" bindtap="handleTap1">
outer view
<view id="middle" catchtap="handleTap2">
middle view
<view id="inner" bindtap="handleTap3">
inner view
</view>
</view>
</view>
因?yàn)閔andleTap2是catchtap,所以:
點(diǎn)擊 inner view,會(huì)先后觸發(fā) handleTap3、handleTap2
點(diǎn)擊 middle view,只會(huì)觸發(fā) handleTap2
點(diǎn)擊 outer view,會(huì)觸發(fā) handleTap1
事件對(duì)象
如無特殊說明,當(dāng)組件觸發(fā)事件時(shí),邏輯層綁定該事件的處理函數(shù)會(huì)收到一個(gè)事件對(duì)象。
BaseEvent 基礎(chǔ)事件對(duì)象屬性列表:
| 屬性 | 類型 | 說明 |
|---|---|---|
| type | String | 事件類型 |
| timeStamp | Integer | 事件生成時(shí)的時(shí)間戳 |
| target | Object | 觸發(fā)事件的組件的一些屬性值集合 |
| currentTarget | Object | 當(dāng)前組件的一些屬性值集合 |
CustomEvent 自定義事件對(duì)象屬性列表(繼承 BaseEvent):
什么是自定義事件呢,你可以簡(jiǎn)單的理解為:在觸發(fā)子組件的一些事件的時(shí)候,同時(shí)也能觸發(fā)父組件對(duì)應(yīng)的事件并對(duì)父組件中的某些數(shù)據(jù)進(jìn)行修改的事件就是自定義事件
| 屬性 | 類型 | 說明 |
|---|---|---|
| detail | Object | 額外的信息 |
TouchEvent 觸摸事件對(duì)象屬性列表(繼承 BaseEvent):
| 屬性 | 類型 | 說明 |
|---|---|---|
| touches | Array | 觸摸事件,當(dāng)前停留在屏幕中的觸摸點(diǎn)信息的數(shù)組 |
| changedTouches | Array | 觸摸事件,當(dāng)前變化的觸摸點(diǎn)信息的數(shù)組 |
特殊事件: <canvas> 中的觸摸事件不可冒泡,所以沒有 currentTarget。
target
觸發(fā)事件的源組件。
| 屬性 | 類型 | 說明 |
|---|---|---|
| id | String | 事件源組件的id |
| tagName | String | 當(dāng)前組件的類型 |
| dataset | Object | 事件源組件上由data-開頭的自定義屬性組成的集合 |
currentTarget
事件綁定的當(dāng)前組件。
| 屬性 | 類型 | 說明 |
|---|---|---|
| id | String | 當(dāng)前組件的id |
| tagName | String | 當(dāng)前組件的類型 |
| dataset | Object | 當(dāng)前組件上由data-開頭的自定義屬性組成的集合 |
自定義組件
當(dāng)我們?cè)谠O(shè)計(jì)我們項(xiàng)目的時(shí)候會(huì)發(fā)現(xiàn)在不同的頁面中,有時(shí)候會(huì)用到相同的功能模塊,此時(shí)我們就可以將這些相同的部分提取出來并且單獨(dú)設(shè)為一個(gè)"頁面",然后在要應(yīng)用到它的地方引用就可以了。
在上面我介紹了,自定義組件其實(shí)就像是一個(gè)頁面,所以我們?cè)诰帉懰臅r(shí)候也應(yīng)該像設(shè)計(jì)頁面一樣,具備json wxml wxss js這四個(gè)文件
前期準(zhǔn)備 1.首先,新建一個(gè)名為wxcomponent的項(xiàng)目, 2.在pages文件夾下創(chuàng)建一個(gè)components文件夾用來盛放我們所有的自定義組件. 3.在components文件夾下創(chuàng)建一個(gè)cpt的文件夾用來盛放cpt這個(gè)自定義組件,并分別創(chuàng)建好對(duì)應(yīng)的配置文件,如下圖:

自定義組件聲明
要在cpt.json中進(jìn)行自定義組件聲明,也就是告訴開發(fā)者這是一個(gè)組件:
{
"component": true
}
設(shè)計(jì)組件結(jié)構(gòu)
在 wxml 文件中編寫組件模版,在 wxss 文件中加入組件樣式: cpt.wxml文件
<!-- 這是自定義組件的內(nèi)部WXML結(jié)構(gòu) -->
<view class="inner">
{{innerText}}
<button bindtap='customMethod'>點(diǎn)擊</button>
<slot></slot>
</view>
cpt.wxss文件
/* 這里的樣式只應(yīng)用于這個(gè)自定義組件 */
.inner {
color: red;
}
這里的`<slot></slot>暫時(shí)可以不用管它.
并且自定義組件在設(shè)計(jì)結(jié)構(gòu)的時(shí)候是不應(yīng)該使用給便簽加上id或者使用屬性選擇器和標(biāo)簽名選擇器的. 這是因?yàn)榻M件就是被我們那里重用的,而頁面中只能允許有一個(gè)id.
PS:公用樣式在子組件中無效
注冊(cè)組件
在自定義組件的js文件中,需要使用 Component() 來注冊(cè)組件,并提供組件的屬性定義、內(nèi)部數(shù)據(jù)和自定義方法,如在cpt.js中:
Component({
properties: {
// 這里定義了innerText屬性,屬性值可以在組件使用時(shí)指定
innerText: {
type: String,
value: 'default value',
}
},
data: {
// 這里是一些組件內(nèi)部數(shù)據(jù)
someData: 1
},
methods: {
// 這里是一個(gè)自定義方法
customMethod: function () {
console.log('customMethod')
}
}
})
使用自定義組件
這里我為了簡(jiǎn)便一點(diǎn),就直接用自帶的logs頁面來進(jìn)行自定義組件的調(diào)用吧. 首先,你應(yīng)該在你要用組件的那個(gè)頁面中引用聲明.也就是在.json文件. 如在logs.json中:
{
"navigationBarTitleText": "查看啟動(dòng)日志",
"usingComponents": {
"component-tag-name": "../components/cpt/cpt"
}
}
接下來我們就可以在頁面中像使用其他組件一樣的使用自定義組件了. 比如我在logs.wxml中使用:
<!--logs.wxml-->
<view class="container log-list">
<!-- 以下是對(duì)一個(gè)自定義組件的引用 -->
<component-tag-name inner-text="Some text"></component-tag-name>
</view>
跳轉(zhuǎn)到logs頁面如下圖的效果:

使用slot
在上面的例子中,在cpt.wxml中寫入了<slot></slot>標(biāo)簽,在引用cpt這個(gè)組件時(shí)我們要是不在組件的標(biāo)簽中寫入其他的內(nèi)容,是不會(huì)顯示<slot>標(biāo)簽的
也就是說如果我們把上面logs.wxml改動(dòng)一下:
<!--logs.wxml-->
<view class="container log-list">
<!-- 以下是對(duì)一個(gè)自定義組件的引用 -->
<component-tag-name inner-text="Some text">
<view>這里是插入到組件slot中的內(nèi)容</view>
</component-tag-name>
</view>
并且<slot></slot>的位置在哪里也是由你在設(shè)計(jì)cpt組件時(shí)決定的 上面的例子中我是將slot放在button之下:
<!-- 這是自定義組件的內(nèi)部WXML結(jié)構(gòu) -->
<view class="inner">
{{innerText}}
<button bindtap='customMethod'>點(diǎn)擊</button>
<slot></slot>
</view>
你也可以將它放在其他位置來達(dá)到不同的效果.
使用多個(gè)slot
正常情況下,一個(gè)組件中只有一個(gè)slot,但有時(shí)候我們的自定義組件可能不止使用一個(gè)slot,別怕,我們的微信小程序也是可以允許你這樣的. 需要使用多slot時(shí),可以在組件js中聲明啟用 1.在cpt.json(你自定義組件的json文件)中聲明
Component({
options: {
multipleSlots: true // 在組件定義時(shí)的選項(xiàng)中啟用多slot支持
},
properties: { /* ... */ },
methods: { /* ... */ }
})
2.此時(shí),可以在這個(gè)組件的wxml中使用多個(gè)slot,以不同的 name 來區(qū)分:
<!-- 這是自定義組件的內(nèi)部WXML結(jié)構(gòu) -->
<view class="inner">
<slot name="header"></slot> <-- 一定要記得使用name屬性 -->
{{innerText}}
<button bindtap='customMethod'>點(diǎn)擊</button>
<slot name="footer"></slot>
</view>
3.使用時(shí),用 slot 屬性來將節(jié)點(diǎn)插入到不同的slot上。
<!--logs.wxml-->
<view class="container log-list">
<!-- 以下是對(duì)一個(gè)自定義組件的引用 -->
<component-tag-name inner-text="Some text">
<view slot="header">頭部的內(nèi)容</view>
<view slot="footer">底部的內(nèi)容</view>
</component-tag-name>
</view>
組件數(shù)據(jù)的傳遞
組件之間的數(shù)據(jù)傳遞分為很多種,例如,在上級(jí)組件傳遞數(shù)據(jù)、事件給下級(jí)頁面,上級(jí)頁面監(jiān)聽下級(jí)頁面的事件回調(diào),跨級(jí)的數(shù)據(jù)傳遞,例如,在首頁將獲取的列表數(shù)據(jù)傳遞給列表組件:
上級(jí)組件:
wxml:
<component-list list-data="{{ListData}}"></component-list></pre>
js
Page({
data: {
listData:[
{ title: "沒點(diǎn)才藝,不敢結(jié)婚" },
{ title: "當(dāng)年母親因超生將1歲兒子送走,如今患病求助遭拒:他年薪55萬,我實(shí)在沒辦法" },
{ title: "男生什么情況下會(huì)對(duì)女生真正失望?" },
{ title: "馬蓉被人背著匆匆逃離醫(yī)院,你是過街老鼠嗎?慢慢走不行嗎?非得讓我把鼻涕泡笑出來!" },
{ title: "趁年輕要對(duì)老婆好點(diǎn),否則老了沒人推你" },
{ title: "戀愛需謹(jǐn)慎 自己養(yǎng)的祖宗 跪著也得哄完!" },
{ title: "這喝水的聲音也太可愛了" },
],
},
})
下級(jí)組件:
wxml:
<view wx:for="{{ListData}}">
<view class="item">{{item.data}}</view>
......
</view>
?
js:
Component({
properties: {
ListData: {
type: Array,
value: [],
observer: function(newData, oldData){
//表示屬性值被更改時(shí)的響應(yīng)函數(shù)
}
}
},
data: {
someData: {}
},
methods: {
customMethod: function(){}
}
})
可以看到,組件的寫法和頁面基本一樣,只是Page變成了Component,這里要注意,只要是由上層組件傳遞過來的數(shù)據(jù),都應(yīng)該在properties里聲明,數(shù)據(jù)類型是必須值,而observer則是監(jiān)聽數(shù)據(jù)變化后產(chǎn)生的事件,例如,上級(jí)頁面的傳遞的值產(chǎn)生變化了,就可以在observer里捕獲到兩個(gè)值newData, oldData,在observer里可以調(diào)用該組件的methods,去做不同的操作。同樣,組件也有生命周期,這點(diǎn)和page略有區(qū)別,文檔里對(duì)這一點(diǎn)寫的還是很詳細(xì)的。
自定義事件
觸發(fā)事件的源組件。
什么是自定義事件呢,你可以簡(jiǎn)單的理解為:在觸發(fā)子組件的一些事件的時(shí)候,同時(shí)也能觸發(fā)父組件對(duì)應(yīng)的事件并對(duì)父組件中的某些數(shù)據(jù)進(jìn)行修改的事件就是自定義事件.
例:
子組件
methods: {
delete(){
let list = this.data.listData
list.splice(-1, 1)
this.setData({
listData: list
})
//自定義事件向父組件傳參
this.triggerEvent('myevent', this.data.listData.length)
},
}
父組件
index.wxml
<component-tag-name bindmyevent="onMyEvent" list-data="{{listData}}">
</component-tag-name>
js
//自定義方法接收子組件傳參
onMyEvent(e){
this.setData({
total: e.detail
})
}