首先從官方文檔給的框架說起,微信小程序官方文檔給出了app.js, app.json, app.wxss. 先從這三個(gè)文件說起. - app.js 這個(gè)文件是整個(gè)小程序的入口文件,開發(fā)者的邏輯代碼在這里面實(shí)現(xiàn),同時(shí)在這個(gè)文件夾里面可以定義全局變量. - app.json 這個(gè)文件可以對(duì)小程序進(jìn)行全局配置,決定頁面文件的路徑,窗口表現(xiàn),設(shè)置網(wǎng)絡(luò)超時(shí)時(shí)間,設(shè)置多tab等. - app.wxss 是小程序的公共樣式表.(為了適應(yīng)廣大的前端開發(fā)者,我們的 WXSS 具有 CSS 大部分特性。 同時(shí)為了更適合開發(fā)微信小程序,我們對(duì) CSS 進(jìn)行了擴(kuò)充以及修改。)
接著我們就結(jié)合官方給出的代碼具體說一下上面提到的三個(gè)文件.
"pages": [ "pages/index/index", "pages/logs/index" ]
可以看出,每一項(xiàng)分別對(duì)應(yīng)的都是實(shí)現(xiàn)文件的路徑以及他的文件名. 注意:這個(gè)配置里面的第一行配置是它的初始頁面,例如上面代碼的初始頁面就是index這個(gè)配置項(xiàng)是用來設(shè)置小程序的狀態(tài)欄、導(dǎo)航條、標(biāo)題、窗口背景色。他給出了六個(gè)屬性(navigationBarBackgroundColor(HexColor), navigationBarTextStyle(String-(black,white)), navigationBarTitleText(String), backgroundColor(HexColor), backgroundTextStyle(String-(dark,light)), enablePullDownRefresh(Boolean)),開發(fā)者可以根據(jù)自己的需求來進(jìn)行配置.
我們?cè)敿?xì)說一下這幾個(gè)屬性分別的功能:
這個(gè)配置項(xiàng)是用來配置頁面底部的tab欄的,開發(fā)者可以根據(jù)自己的需求來進(jìn)行配置.
注意: tabBar是一個(gè)數(shù)組,只能配置最少2個(gè),最多5個(gè),而且tab欄的順序是按照數(shù)組的排序來的.
tabBar官方給出了一下五個(gè)屬性(color(HexColor), selectedColor(HexColor), backgroundColor(HexColor), borderStyle(String), list(Array) ).
接下來說說我對(duì)這五個(gè)屬性的理解:
borderStyle 設(shè)置邊框的顏色,現(xiàn)在僅支持(black和white)
上面這四個(gè)屬性就是按照官方給出的API來設(shè)置就可以,下面說一下list屬性.list屬性接受的是一個(gè)數(shù)組(Array),在list下面配置的每一項(xiàng)都是一個(gè)對(duì)象,他們都有以下這四個(gè)屬性(pagePath(String), text(String), iconPath( String), selectedIconPath(String)).
pagePath 這個(gè)定義的是頁面的路徑,但是這個(gè)屬性定義的路徑必須是在pages上定義過的.
text 設(shè)置的是按鈕上的文字
iconPath 是定義icon圖片的路徑,這個(gè)屬性定義的圖片大小不超過40kb selectedIconPath 定義的是當(dāng)選中按鈕之后顯示的圖片,同樣圖片的大小不能超過40kb.
下面是官方給出的效果圖:
它是用來設(shè)置各種網(wǎng)絡(luò)請(qǐng)求的超時(shí)時(shí)間的,單位是毫秒,官方給出了四個(gè)屬性(request, connectSocket, uploadFile, downloadFile)這四個(gè)屬性分別定義的是wx.request, wx.connectSocket, wx.uploadFile, downloadFile 這四個(gè)API的超時(shí)時(shí)間.
如果在app.json將debug配置為true,那么在開發(fā)者工具的控制臺(tái)面板中可以輸出詳細(xì)的調(diào)試信息.
以上就是根據(jù)官方給出的文檔,我學(xué)習(xí)之后對(duì)app.json配置一些心得,下面我們?cè)诳匆幌耡pp.js 這個(gè)文件.
可以看到app.js這個(gè)文件的后綴是js,沒錯(cuò),微信小程序的開發(fā)框架在邏輯層用的語言就是JavaScript.但是微信小程序也在JavaScript的基礎(chǔ)上做了一個(gè)修改,可以稱之為一個(gè)新的輪子.這個(gè)框架可以使開發(fā)者更加方便的調(diào)用一些微信的功能,例如掃一掃,微信支付等一些微信特有的功能.
我們接著回到app.js這個(gè)文件中來,其他的稍后再說.
這個(gè)文件是整個(gè)小程序的入口文件,也可以說是控制整個(gè)小程序生命周期的文件,那么我們就不難想象,我們?cè)谶@個(gè)文件中應(yīng)該實(shí)現(xiàn)的幾個(gè)功能,首先我們肯定需要對(duì)整個(gè)程序進(jìn)行注冊(cè),正好微信給我們提供了一個(gè)app()來實(shí)現(xiàn)對(duì)整個(gè)程序的注冊(cè),同時(shí)app()里面還實(shí)現(xiàn)了對(duì)小程序生命周期的監(jiān)控函數(shù)(onLaunch, onShow, onHide), 其中onLaunch是監(jiān)聽小程序初始化,當(dāng)初始化完成時(shí)會(huì)觸發(fā)onLaunch,當(dāng)然這個(gè)函數(shù)是全局只觸發(fā)一次.onShow是監(jiān)聽小程序的顯示,在小程序啟動(dòng)時(shí)候,或者當(dāng)你從后臺(tái)進(jìn)入到前臺(tái)的時(shí)候就會(huì)觸發(fā)這個(gè)函數(shù).而onHide函數(shù)是監(jiān)聽小程序的隱藏的,當(dāng)你從前臺(tái)切換到后臺(tái)的時(shí)候,會(huì)觸發(fā)onHide.有了這些一個(gè)小程序的實(shí)例基本上算是完成了,當(dāng)然為了讓開發(fā)者加入更多自己的邏輯,微信還提供了讓開發(fā)者在app()中加入自己的邏輯,開發(fā)者可以可以添加任意的函數(shù)或數(shù)據(jù)到 Object 參數(shù)中,用 this 可以訪問.
注意:app()只能定義在app.js中,而且不能注冊(cè)多個(gè).
當(dāng)在app.js中注冊(cè)了實(shí)例之后,如果你想在自己的邏輯頁面調(diào)用它,你可以用getApp()這個(gè)全局函數(shù),這樣你就可以全局調(diào)用app()里面的數(shù)據(jù).
微信給出的官方代碼如下:
注意:getApp()獲取里實(shí)例之后,不要私自調(diào)用生命周期函數(shù). 而且不要在app.js中用getApp()函數(shù),用this就可以調(diào)用app()里面的東西.
基本上app.js就這些東西,還有一些API里面的內(nèi)容會(huì)在后面一一介紹.下面我們就看一下app.wxss這個(gè)文件,一般來說做過網(wǎng)站開發(fā)的(我自己是用php來開發(fā)的,這是我個(gè)人的一點(diǎn)拙見,如有不對(duì)請(qǐng)見諒)相信對(duì)css寫在單獨(dú)的文件中應(yīng)該不會(huì)陌生,這個(gè)app.wxss也是類似的,不過他的的配置是針對(duì)全局的,也就是說如果你在后面的page中沒有重新配置他,那么他就會(huì)調(diào)用這個(gè)文件中的樣式設(shè)置,但是如果你有個(gè)人需求,需要在每個(gè)頁面重新寫樣式,那也沒關(guān)系,他會(huì)自動(dòng)覆蓋宰割文件中的樣式.
當(dāng)你重新創(chuàng)建一個(gè)微信小程序他就會(huì)出現(xiàn)這幾個(gè)文件,以上是我結(jié)合官方文檔對(duì)他們的一些理解,接下來就是page的邏輯,視圖,配置的一些心得.
這一塊就是開發(fā)者自己的業(yè)務(wù)實(shí)現(xiàn)文件了. 每一個(gè)頁面可以放在一個(gè)文件夾中,這個(gè)文件夾中一般包括.js, .json, .wxml, .wxss 這四個(gè)文件,微信官方還建議這四個(gè)文件的名字最好和文件夾的名字一致.這個(gè)便于框架自動(dòng)查找,不需要做更多的配置.
當(dāng)你開始做頁面的功能的時(shí)候這個(gè)時(shí)候在.js,也需要注冊(cè),微信官方給出Page()這個(gè)函數(shù)來注冊(cè)一個(gè)頁面,他接受一個(gè)object參數(shù),用其來指定頁面的初始數(shù)據(jù),生命周期函數(shù),事件處理函數(shù).需要注意的是當(dāng)你在注冊(cè)這個(gè)頁面的時(shí)候要確定在最開始的app.json這個(gè)配置文件中已經(jīng)配置過這個(gè)頁面,而且當(dāng)你對(duì)程序有所改變的時(shí)候也要確保app.json這個(gè)文件中的內(nèi)容也隨之相應(yīng)改動(dòng).
微信給Page()函數(shù)一下幾個(gè)屬性(data(Object), onLoad(function), onReady(Function), onShow(Function), onHide(Function), onUpload(Function), onPullDownRefresh(Function)),而且你也可以添加任意函數(shù)或者數(shù)據(jù)到object參數(shù)中,在這個(gè)頁面用this即可訪問.
下面就簡單的介紹一下這幾個(gè)官方給出的屬性:
下面是微信給出的官方代碼:
上面說了用data屬性來設(shè)置頁面的初始化數(shù)據(jù),但是如果我們想改變數(shù)據(jù)里面的值,怎么辦??那么我們就介紹一個(gè)微信官方給我們提供的setData()函數(shù),這個(gè)函數(shù)可以將數(shù)據(jù)從邏輯層發(fā)送到數(shù)據(jù)層,同時(shí)還可以改變this.data的值.
setData()接受一個(gè)對(duì)象參數(shù),讓數(shù)據(jù)以key,value的形式表示將this.data中key對(duì)應(yīng)的值改變成value.下面是微信官方給出的page的生命周期的圖片:
在小程序中的所有頁面路由全部由框架進(jìn)行管理,對(duì)于路由的觸發(fā)方式以及頁面的生命周期函數(shù)可以通過調(diào)用API來進(jìn)行..
下面我們就簡單的介紹一下微信小程序的API.
微信小程序框架給我們提供了豐富的微信原生API,可以方便的調(diào)用微信提供的能力,如獲取用戶信息,本地存儲(chǔ),支付功能等.
下面是微信關(guān)于API提供的說明:
wx.on 開頭的API是監(jiān)聽某個(gè)事件發(fā)生的API接口,接受一個(gè)CALLBACK函數(shù)作為參數(shù),當(dāng)事件觸發(fā)時(shí),會(huì)調(diào)用CALLBACK函數(shù).
OBJECT 可以指定success,fail,complete來接受接口調(diào)用結(jié)果.
API的具體調(diào)用請(qǐng)看 微信小程序API文檔
因?yàn)楝F(xiàn)在微信小程序還在內(nèi)測期間,我也沒有內(nèi)測號(hào),所以具體的調(diào)用API代碼需要在微信小程序開放之后,根據(jù)具體的邏輯進(jìn)行實(shí)現(xiàn).而且微信API文檔已經(jīng)給的非常清楚,相信調(diào)用不會(huì)太過困難.
上面的這些就是微信小程序page的頁面注冊(cè)以及API功能實(shí)現(xiàn),但是我們知道光有這些是不夠的,在互聯(lián)網(wǎng)發(fā)展到現(xiàn)在我們更加注重的是人機(jī)交互,讓用戶有一個(gè)更好的體驗(yàn)才算是 一個(gè)好的程序,那么接下來我們就講講微信小程序是如何對(duì)頁面進(jìn)行渲染的。
在微信小程序中采用了微信自己原生的渲染方式。微信小程序的頁面布局采用的是wxml,然后結(jié)合基礎(chǔ)組件,事件系統(tǒng)構(gòu)建出來頁面的結(jié)構(gòu)。
wxml中有數(shù)據(jù)綁定,條件渲染,列表渲染, 模版,事件, 引用這幾種方式,下面我們就具體說說這幾種方式。
數(shù)據(jù)綁定 在上面我們已經(jīng)說過了在Page()注冊(cè)頁面的時(shí)候,里面會(huì)有一個(gè)data屬性來定義初始化數(shù)據(jù),現(xiàn)在頁面渲染的數(shù)據(jù)綁定的時(shí)候就需要調(diào)用data里面的數(shù)據(jù)了。下面看一下官方給出的例子。
從上面的代碼可以看出來在視圖層接受邏輯層的代碼的時(shí)候需要用2個(gè)大括號(hào)把數(shù)據(jù)的鍵值包起來就可以得到數(shù)據(jù)的值。當(dāng)然在視圖層還可以進(jìn)行運(yùn)算(三元運(yùn)算,算術(shù)運(yùn)算),邏輯判斷,字符串運(yùn)算,而且還可以在大括號(hào)里面進(jìn)行組合(數(shù)組,對(duì)象(雖然可以隨意組合,但是如果后面的變量名和前面的變量名相同的話,那么后面的會(huì)覆蓋前面的))。
條件渲染 顧名思義所謂的條件渲染,就是通過條件來判斷是否需要渲染該代碼塊。條件渲染主要是用到wx:if 和 block wx:if 這兩個(gè),第一個(gè)相信好理解,第二個(gè)是在block里面進(jìn)行條件渲染,這里我們特別說明一下< block/>并不是一個(gè)組件,它僅僅是一個(gè)包裝元素,不會(huì)在頁面中做任何渲染,只接受控制屬性。和我們以前的邏輯編程類似,既然有了wx:if ,那么我們也會(huì)有wx:elseif和wx.else,這幾個(gè)組合起來,可以使條件渲染更加靈活。
在這里官方文檔中提到了一個(gè)wx:if和hidden的對(duì)比,通過合理的運(yùn)用這兩種方法可以使你的程序更優(yōu)。下面我們就是說說他們倆的區(qū)別:
因?yàn)閣x:if之中也可能包含數(shù)據(jù)綁定,所以當(dāng)wx:if的條件值切換時(shí),框架有一個(gè)局部渲染的過程,他會(huì)確保條件在切換是銷毀或者重新渲染。同時(shí)wx:if也是有惰性的,如果初始渲染條件為false,框架什么也不會(huì)做,只有在條件第一次變?yōu)檎娴臅r(shí)候才會(huì)開始渲染。相比之下hidden就簡單的多,組件始終都會(huì)被渲染,只是簡單的控制顯示和隱藏,一般來說,wx:if 有更高的切換消耗,而hidden有更高的初始渲染消耗,你可以根據(jù)自己的需求來調(diào)用。
列表渲染 -- wx:for
下面我們就說說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)的變量名為item,,當(dāng)然你也可以根據(jù)自己的需要來重新定義這兩個(gè)名字,使用wx:for-item可以指定數(shù)組當(dāng)前元素的變量名,wx:for-index可以指定數(shù)組當(dāng)前下標(biāo)的變量名,wx:for也可以嵌套,這個(gè)時(shí)候就需要改變默認(rèn)框架給定義的名字了。
下面是官方給出的事例代碼:
模版
WXML提供模版(template),可以在模版中定義代碼片段,然后在不同的地方調(diào)用.微信小程序的模版可以用name來命名它的名字,在使用的時(shí)候用is來聲明使用的模版,然后將模版所需要的data傳入即可,下面我們用官方文檔給的代碼來看一下如何聲明及調(diào)用模版.
通過上面對(duì)條件渲染的介紹,我們可以看到在循環(huán)掉數(shù)組[1,2,3,4,5]之后item數(shù)組屬性在三元運(yùn)算中判斷調(diào)用哪一個(gè)模版.
在這兒再多說一句模版也有自己的作用域,只能使用data傳入的數(shù)據(jù),當(dāng)然data傳入的數(shù)據(jù)可以是你自己新建的數(shù)據(jù),也可以是你在配置中寫好的初始化數(shù)據(jù).
好了現(xiàn)在我們說完模版了,可能有的同學(xué)就該想了,我寫好模版之后該如何調(diào)用它,如果他們是在一個(gè)頁面那肯定沒問題,但是這樣的話可用性還是很差啊,如果我想把模版單獨(dú)放在一個(gè)頁面,在調(diào)用它的時(shí)候該怎么辦啊?沒關(guān)系,微信小程序早就考慮到了,那么我們接下來就說說引用.
引用
WXML提供兩種引用方式import和include.
接下來我們就先說說import這種方式,我們就結(jié)合代碼來看,它調(diào)用在不同頁面的模版消息如下:
<!-- item.wxml --><template name="item"> <text>{{text}}</text></template>
在 index.wxml 中引用了 item.wxml,就可以使用item模板:
<import src="item.wxml"/><template is="item" data="{{text: 'forbar'}}"/>
這里要注意一下,import引用也是有作用域這個(gè)概念存在的,它只會(huì)定義import目標(biāo)文件中定義的template,而不會(huì)import目標(biāo)文件import中的template.簡而言之就是import只能引用template而不能引用import.
上面說了import是如何引用的,那么我們接著看一下include是怎么引用的.
include引用和import唯一不同點(diǎn)就是他的引用相當(dāng)于復(fù)制,他會(huì)復(fù)制< template>里面的全部內(nèi)容,但是不包含< template>,看一下代碼相信你可以理解的更加明白.
<!-- index.wxml --><include src="header.wxml"/><view> body </view><include src="footer.wxml"/>
<!-- header.wxml --><view> header </view>
<!-- footer.wxml --><view> footer </view>
上面我們說的視圖層這些方法已經(jīng)可以構(gòu)成一個(gè)靜態(tài)的頁面了,但我們現(xiàn)在是21世紀(jì)啊,一個(gè)沒有人機(jī)交互的程序怎么能在這個(gè)世界生存下來了?在用戶體驗(yàn)至上的今天,微信小程序不可能不考慮到這一點(diǎn),接下來我們就說說視圖層的事件方法.
先來說說什么是事件,相信有的人看到這兒肯定是一臉懵逼,你這說的啥玩意兒,說的這么專業(yè),我還不如看文檔去.那么我們就說說什么是事件.
事件就是一種頁面到邏輯層的通訊方式,比如說你的操作想得到機(jī)器的反饋,這時(shí)候就用到事件了.事件可以將用戶的行為反饋到邏輯層進(jìn)行處理.
說到這兒不禁又有一個(gè)問題,那他是怎么用的呢? 事件可以綁定到組件上,當(dāng)觸發(fā)事件,就會(huì)執(zhí)行邏輯層對(duì)應(yīng)的事件處理函數(shù),當(dāng)然為了更加方便人機(jī)交互,用戶還可以攜帶額外的信息,如id,data等.
可能有人看完剛才的一段就說了,好了,你剛才說的事件解釋的差不多了,可是你為什么有冒出一個(gè)組件,這讓我這么理解?
既然說到組件了,我們就先簡單的了解一下,在之后的組件板塊再詳說,先保證大家能看懂什么是事件就好了.
為什么要有組件呢?組件是框架為了開發(fā)者進(jìn)行快速的開發(fā)而設(shè)計(jì)的.
那什么是組件呢? 組件是視圖層的基本組成單元,在微信小程序中組件自帶一些功能與微信風(fēng)格的樣式,一個(gè)組件通常包括開始標(biāo)簽和結(jié)束標(biāo)簽,屬性是用來修飾這個(gè)組件,內(nèi)容在兩個(gè)標(biāo)簽之內(nèi).
<tagname property="value"> Content goes here ...</tagename>
在這里需要注意一點(diǎn),組件和屬性都是小寫,并且以"-"進(jìn)行連接.
簡單的介紹一下組件,那我們繼續(xù)說事件.
事件分為冒泡事件和非冒泡事件,冒泡事件是當(dāng)一個(gè)組件上的事件被觸發(fā)后,該事件會(huì)向父節(jié)點(diǎn)傳遞,而非冒泡事件則不會(huì).
現(xiàn)在微信小程序給出的冒泡事件僅僅有6個(gè)(touchstart,touchmove, touchcancel,touchend,tap, longtap),下圖是他們分別對(duì)應(yīng)的觸發(fā)條件.
剩下的都屬于非冒泡事件.
接下來我們就說說事件怎么用?
事件是通過事件綁定來實(shí)現(xiàn)的.它的寫法是以key,value的形式來寫的.key以bind 和catch 開頭,然后跟上事件的類型. value 是一個(gè)字符串,需要在對(duì)應(yīng)的page中定義同名的函數(shù),不然當(dāng)觸發(fā)事件的時(shí)候會(huì)報(bào)錯(cuò).(bind 事件綁定不會(huì)阻止冒泡事件向上冒泡,而catch 可以阻止冒泡事件向上冒泡).
說完了如何進(jìn)行事件綁定了,我們?cè)僬f說,當(dāng)事件觸發(fā)是邏輯層的事件處理函數(shù)會(huì)收到什么? 事件處理函數(shù)會(huì)收到一個(gè)事件對(duì)象. 那么這個(gè)事件對(duì)象里面都有什么屬性呢?? 里面的屬性有(type, timeStamp, target, currentTarget, touches, detail),下面是他們的一些說明:
其他的屬性按照上面的說明簡單了解即可,在這里我們說一下target和currentTarget中的dataset,我們知道在組件中可以定義數(shù)據(jù),這些數(shù)據(jù)會(huì)通過事件傳遞給 SERVICE書寫方式: 以data-開頭,多個(gè)單詞由連字符-鏈接,不能有大寫(大寫會(huì)自動(dòng)轉(zhuǎn)成小寫)如data-element-type,最終在 event.target.dataset 中會(huì)將連字符轉(zhuǎn)成駝峰e(cuò)lementType。用一段代碼來說話相信大家就更清楚了.
<view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
Page({
bindViewTap:function(event){
event.target.dataset.alphaBeta == 1 // - 會(huì)轉(zhuǎn)為駝峰寫法
event.target.dataset.alphabeta == 2 // 大寫會(huì)轉(zhuǎn)為小寫
}
})
我不知道大家感覺怎么樣,要是我自己剛開始看我寫的這一大段內(nèi)容,我感覺我就該罵娘了,不是說么NO圖NO BB,下面我就給大家上代碼,相信看完之后事件這一塊基本上就明白了.
//視圖層的事件綁定
<view id="tapTest" data-hi="MINA" bindtap="tapName"> Click me! </view>
//邏輯層的事件處理函數(shù)
Page({
tapName: function(event) {
console.log(event)
}
})
//邏輯層的事件處理函數(shù)輸出的信息
//邏輯層的事件處理函數(shù)輸出的信息
{
"type": "tap",
"timeStamp": 1252,
"target": {
"id": "tapTest",
"offsetLeft": 0,
"offsetTop": 0,
"dataset": { "hi": "MINA" }
},
"currentTarget": {
"id": "tapTest",
"offsetLeft": 0,
"offsetTop": 0,
"dataset": { "hi": "MINA" }
},
"touches": [{
"pageX": 30,
"pageY": 12,
"clientX": 30,
"clientY": 12,
"screenX": 112, "screenY": 151
}],
"detail": { "x": 30, "y": 12}}
到這兒WXML的頁面結(jié)構(gòu)就說完了,接著我們簡單說說WXSS就基本說完了.
在WXSS中引入了新的 尺寸單位rpx 它規(guī)定1rpx=0.5px = 1物理像素
WXSS的樣式導(dǎo)入使用@import語句可以導(dǎo)入外聯(lián)樣式表,@import后跟需要導(dǎo)入的外聯(lián)樣式表的相對(duì)路徑,用;表示語句結(jié)束.剩下的內(nèi)容基本上和css相差不大,有興趣的可以看一下官方文檔WXSS