最近幾個(gè)月因?yàn)楣镜臉I(yè)務(wù)需求,一直在折騰小程序,從開始的完全不熟悉,到后面被各種坑折磨,是時(shí)候?qū)懸黄偨Y(jié)了,避免下一次遇到還找不到解決的方案。
配置項(xiàng)app.json和page.json
app.json
首先,需要確定的是,app.json 是小程序的全局配置,放在根目錄下。
常用的一些字段如下:
-
pages: 這個(gè)用于設(shè)置頁面的路徑,通常訪問的頁面都放在pages文件夾里面,且必須在這個(gè)全局配置文件中設(shè)置好路徑,否則訪問的時(shí)候會(huì)報(bào)錯(cuò)找不到該路徑, 寫在 pages 字段的第一個(gè)頁面就是這個(gè)小程序的首頁 (打開小程序看到的第一個(gè)頁面)
-
window: 全局樣式的配置
-
導(dǎo)航欄相關(guān):可配置導(dǎo)航欄背景顏色、標(biāo)題顏色,標(biāo)題內(nèi)容,
-
可以隱藏導(dǎo)航欄(navigationStyle設(shè)置為custom,但需要注意, 自定義導(dǎo)航欄仍然保留右上角膠囊,且沒有返回鍵,如果想要實(shí)現(xiàn)返回功能,需要自己自定義返回的樣式和功能 ),==該設(shè)置對(duì)web-view 組件無效==
-
窗口的背景色, backgroundColor,(即小程序下拉時(shí)露出的那一截),另外,僅ios支持的還有backgroundColorTop和backgroundColorBottom, 頂部和底部窗口的背景色
-
下拉loading的樣式,只有黑色和白色(dark / light)
-
enablePullDownRefresh ,小程序默認(rèn)頁面是沒有下拉刷新功能的,如果在app.json中配置該項(xiàng)為true,則所有頁面都可以生效。如果只想在單個(gè)頁面使用下拉刷新,需要在對(duì)應(yīng)的page.json中進(jìn)行配置
-
onReachBottomDistance, 上拉加載更多生效時(shí)距頁面底部距離,默認(rèn)為50px
-
屏幕旋轉(zhuǎn),pageOrientation, 暫時(shí)還沒有用到過,支持 auto / portrait / landscape,默認(rèn)為portrait豎屏顯示,
-
tabbar: tab欄設(shè)置
-
位置:支持頂部和底部(通常使用底部tab欄), position(bottom / top)
-
tab列表 list: 文字以及對(duì)應(yīng)的路徑
-
最少2個(gè),最多5個(gè)
-
pagePath,頁面路徑(必須是pages中定義的路徑)
-
text, tab上的文字
-
iconPath, 圖片路徑,( 大小限制為 40kb,建議尺寸為 81px * 81px,不支持網(wǎng)絡(luò)圖片 )
-
selectedIconPath,選中時(shí)的圖片路徑。限制同上
-
樣式相關(guān):color字體顏色,selectedColor選中文字的顏色,backgroundColor是tab欄背景色 ,borderStyle上邊框顏色,
-
custom是否自定義,默認(rèn)為否, 具體文檔參考: 自定義tabBar
-
networkTimeout(設(shè)置網(wǎng)絡(luò)請(qǐng)求的超時(shí)時(shí)間)
-
request
-
connectSocket
-
uploadFile
-
downloadFile
-
debug, 開啟調(diào)試,會(huì)輸出Page 的注冊(cè),頁面路由,數(shù)據(jù)更新,事件觸發(fā)等信息,方便查看生命周期的調(diào)試
-
navigateToMiniProgramAppIdList, 跳轉(zhuǎn)到其他小程序時(shí),需要先在app.json中進(jìn)行聲明
-
usingComponents,如果在app.json中聲明該組件,則全局可以使用該自定義組件,不需要再在page的json中聲明
-
permission, 用于授權(quán)相關(guān),平時(shí)項(xiàng)目中是自己寫的頁面,調(diào)用button的open-type屬性喚起授權(quán),其實(shí)可以通過插件功能頁來實(shí)現(xiàn),比如授權(quán)昵稱, 用戶信息功能頁
page.json
頁面的樣式配置優(yōu)先級(jí)比全局配置中的window高。
-
可以設(shè)置導(dǎo)航欄背景顏色、導(dǎo)航欄標(biāo)題顏色,導(dǎo)航欄標(biāo)題,
-
可以隱藏導(dǎo)航欄,custom 自定義導(dǎo)航欄,只保留右上角膠囊按鈕
-
窗口的背景色 , 以及ios支持頂部和底部窗口的背景色
-
backgroundTextStyle,下拉 loading 的樣式,僅支持 dark / light
-
enablePullDownRefresh開啟下拉刷新,這個(gè)屬性只控制當(dāng)前的page頁面可以刷新
-
onReachBottomDistance,上拉加載更多生效時(shí)距頁面底部距離,默認(rèn)為50px
-
pageOrientation,屏幕旋轉(zhuǎn)設(shè)置
-
disableScroll ,為 true 則頁面整體不能上下滾動(dòng)。只在頁面配置中有效,無法在 app.json 中設(shè)置
-
disableSwipeBack, 禁止頁面右滑手勢(shì)返回
-
usingComponents, 使用自定義組件,如果沒有在頁面的json中聲明,直接使用組件會(huì)報(bào)錯(cuò)
sitemap.json文件(用于微信索引)
默認(rèn)規(guī)則為都默認(rèn)被索引:
{"action": "allow", "page": "*"}
語法區(qū)別
wxml文件跟html的區(qū)別:
-
沒有div, p, span, 使用view代替div, text代替span
-
wx:if的使用同vue中的v-if, 但使用上略有區(qū)別,不管在標(biāo)簽中還是文本上,都是使用雙大括號(hào)來表示插值, wx:for="{{array}}" ,
-
條件渲染有wx:if, wx:elif, wx:else, 使用方式: <view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
-
尤其注意,如果是使用boolean類型的值,不要直接在雙引號(hào)內(nèi)直接寫,也需要寫在雙大括號(hào)里面。如 <checkbox checked="{{false}}"> </checkbox>
-
列表渲染 wx:for="{{array}}" , 可直接使用item和index,也可以使用 wx:for-item="idx" , 和 wx:for-item="itemName" 重新指定index和item的key值, 花括號(hào)和引號(hào)之間如果有空格,將最終被解析成為字符串
-
wxml文件中有一個(gè)標(biāo)簽是block, 僅僅是一個(gè)包裝元素,不會(huì)在頁面中做任何渲染,只接受控制屬性
-
wx:key的值只能是字符串或者 "*this", wx:key="*this" 表示for 循環(huán)中的 item 本身, 但是要保證這個(gè)item本身是一個(gè)唯一的字符串或者數(shù)字, 當(dāng)key綁定的是對(duì)象的時(shí)候會(huì)報(bào)錯(cuò)
問題思考?
wx:if 和 hidden 該怎么合理的判斷使用場(chǎng)景?
-
wx:if 是惰性的,只有為true時(shí)才會(huì)局部渲染,當(dāng) wx:if 的條件值切換時(shí),條件塊會(huì)在切換時(shí)銷毀或重新渲染。
-
而hidden始終會(huì)被渲染,只是控制顯示與隱藏
-
所以,如果需要頻繁切換的情景下,用 hidden 更好,如果在運(yùn)行時(shí)條件不大可能改變則 wx:if 較好
組件
基礎(chǔ)組件
-
組件的公共屬性:
-
id, class, style, hidden, data- , bind /catch*
-
視圖容器:
-
可移動(dòng): movable-area, movable-view。 其中,movable-view必須在 movable-area 組件中,并且必須是直接子節(jié)點(diǎn)
-
覆蓋原生組件:cover-view, cover-image,主要用于覆蓋 map、video、canvas、camera、live-player、live-pusher等級(jí)別高的原生組件。 注意,在cover-view中只能嵌套cover-view、cover-image和button
-
可滾動(dòng)的視圖區(qū)域:scroll-view, 豎向滾動(dòng)時(shí),需要給scroll-view一個(gè)固定高度
-
滑塊視圖容器: swiper, 其中只能放置swiper-item組件(常用于輪播圖)
-
視圖容器view, 如果想使用hover的樣式,可以指定按下去的樣式類,跟hover相關(guān)的屬性: hover-class,hover-stop-propagation, hover-start-time, hover-stay-time
-
圖標(biāo)icon,在小程序中可以使用自帶的一些icon圖標(biāo),可以設(shè)置type、大小、顏色,詳情查看, 小程序icon組件
-
進(jìn)度條,progress, 普通的進(jìn)度條包括動(dòng)畫等可以直接使用該組件
-
富文本,rich-txt, (可以使用該組件渲染html內(nèi)容,傳入html字符串)
-
文本,text, (如果需要展示多個(gè)空格,可以設(shè)置space屬性)
-
按鈕,button,(可以設(shè)置disabled屬性進(jìn)行禁用,防止多次點(diǎn)擊觸發(fā)事件)
-
單選、多選框:radio、radio-goup、checkbox、checkbox-group
-
富文本編輯器,editor
-
表單form,支持switch input checkbox slider radio picker 的提交
-
輸入框input,支持文本、數(shù)字、身份證、帶小數(shù)點(diǎn)的數(shù)字鍵盤等4個(gè)類型,password可以顯示密碼類型,(可以控制鍵盤右下角的文字,使用confirm-type屬性控制,包括“發(fā)送”、“搜索”、“下一個(gè)”、“前往”、“完成”)注意:input無法設(shè)置 font-family,使用的是系統(tǒng)字體
-
滾動(dòng)選擇器,picker,支持普通、多列、時(shí)間、日期、省市選擇器,
-
嵌入頁面的滾動(dòng)選擇器, picker-view, picker-view-column
-
滑動(dòng)選擇器,slider,類似進(jìn)度條不過可以拖動(dòng)
-
開關(guān),switch
-
多行輸入框,textarea
-
導(dǎo)航,navigator,(類似于a標(biāo)簽,可以使用navigate、redirect、switchTab、reLaunch、navigateBack、exit(退出小程序)等類型)
-
系統(tǒng)相機(jī),camera,可以用于掃描二維碼
-
視頻video,(注意,使用video組件在列表中的時(shí)候會(huì)引起小程序頁面卡頓甚至崩潰,目前項(xiàng)目中的解決方案是使用阿里云上傳視頻的截幀圖片來替換掉video組件,只有點(diǎn)擊圖片后才會(huì)播放視頻,查看網(wǎng)上資料說是video的src默認(rèn)為空,解決了viode自動(dòng)下載的bug,使用custom-cache="{{false}}"可以解決視頻緩存中卡住的問題,不過還沒有試過)
-
公眾號(hào)關(guān)注組件,official-account
-
承載網(wǎng)頁的容器,web-view,(適用于第三方網(wǎng)站內(nèi)容的嵌入,注意需要在公眾平臺(tái)配置業(yè)務(wù)域名),避免在鏈接中帶有中文字符,在 iOS中會(huì)有打開白屏的問題,建議加一下encodeURIComponent
原生組件的使用限制
-
原生組件包括:
-
camera
-
canvas
-
input(僅在focus時(shí)表現(xiàn)為原生組件)
-
live-player
-
live-pusher
-
map
-
textarea
-
video
-
層級(jí): 最高,其他組件無論設(shè)置 z-index 為多少,都無法蓋在原生組件上
-
原生組件不能設(shè)置動(dòng)畫、fixed布局、不能使用overflow: hidden來裁剪原生組件的顯示區(qū)域,
-
事件監(jiān)聽不能使用 bind:eventname 的寫法,只支持 bindeventname,不支持 catch 和 capture 的事件綁定方式
事件系統(tǒng)
-
事件處理函數(shù),參數(shù)是event,event的事件內(nèi)容包括:
-
type
-
timeStamp, 事件生成時(shí)的時(shí)間戳
-
target,觸發(fā)事件的 源組件
-
currentTarget,事件綁定的 當(dāng)前組件
-
detail, 自定義事件所攜帶的數(shù)據(jù)
-
touches,一個(gè)數(shù)組,每個(gè)元素為一個(gè) Touch 對(duì)象
-
changedTouches, 有變化的觸摸點(diǎn)
-
dataset:在target或currentTarget的事件對(duì)象中,可以通過dataset獲取當(dāng)前自定義的一些數(shù)據(jù),(在JS文件中使用event.currentTarget.dataset時(shí),dataset的屬性會(huì)自動(dòng)轉(zhuǎn)換字符串, 連字符寫法會(huì)轉(zhuǎn)換成駝峰寫法,而大寫字符會(huì)自動(dòng)轉(zhuǎn)成小寫字符 )
-
mark,類似于dataset,(如果存在同名的 mark ,父節(jié)點(diǎn)的 mark 會(huì)被子節(jié)點(diǎn)覆蓋)
-
頁面的用戶行為:
-
下拉刷新 onPullDownRefresh
-
上拉觸底 onReachBottom
-
頁面滾動(dòng) onPageScroll
-
用戶轉(zhuǎn)發(fā) onShareAppMessage
思考:
-
小程序中bind事件和catch事件有什么區(qū)別?
-
bind事件綁定不會(huì)阻止冒泡事件向上冒泡,
-
catch事件綁定可以阻止冒泡事件向上冒泡
-
target和currentTarget有什么不同?
<view id="outer" bindtap="handleTap1">
outer view
<view id="middle" catchtap="handleTap2">
middle view
<view id="inner" bindtap="handleTap3">
inner view
</view>
</view>
</view>
復(fù)制代碼
如上面這個(gè)示例中,點(diǎn)擊inner view會(huì)觸發(fā)handleTap3,同時(shí)會(huì)冒泡到handleTap2。 對(duì)于handleTap2這個(gè)組件來說,此時(shí)收到事件對(duì)象的target就是inner的元素,而currentTarget是middle的部分
-
mark 和 dataset 有什么區(qū)別?
-
mark 會(huì)包含從觸發(fā)事件的節(jié)點(diǎn)到根節(jié)點(diǎn)上所有的 mark: 屬性值;
-
dataset 僅包含一個(gè)節(jié)點(diǎn)的 data- 屬性值
-
節(jié)點(diǎn)的 mark 不會(huì)做連字符和大小寫轉(zhuǎn)換
小程序相關(guān)機(jī)制
-
小程序框架的邏輯層并非運(yùn)行在瀏覽器中,因此 JavaScript 在 web 中一些能力都無法使用,如 window,document 等
小程序的運(yùn)行機(jī)制:冷啟動(dòng)和熱啟動(dòng)
-
冷啟動(dòng): 首次打開小程序;或小程序銷毀后打開。(冷啟動(dòng)會(huì)觸發(fā)app.js中的onLaunch生命周期函數(shù))
-
熱啟動(dòng): 點(diǎn)擊右上角膠囊退出、或者h(yuǎn)ome鍵離開微信、或者左右滑動(dòng)返回到微信等動(dòng)作,都是熱啟動(dòng),并沒有銷毀小程序,(所以熱啟動(dòng)不會(huì)觸發(fā)onLaunch函數(shù),但會(huì)觸發(fā)onShow函數(shù))
啟動(dòng)場(chǎng)景
-
小程序啟動(dòng)場(chǎng)景分為兩種:
-
從發(fā)現(xiàn)欄、另一個(gè)小程序返回、微信支付、首頁下拉小程序欄等為A場(chǎng)景
-
B場(chǎng)景:打開某個(gè)特定頁面:如轉(zhuǎn)發(fā)分享的卡片鏈接
-
熱啟動(dòng)場(chǎng)景效果:
-
如果重新進(jìn)入的場(chǎng)景和退出時(shí)的場(chǎng)景都是A場(chǎng)景,則保留原來狀態(tài);例如:停留在“個(gè)人中心”頁面,退出后,下拉首頁的小程序列表進(jìn)入后還是會(huì)停留在“個(gè)人中心”頁面,(觸發(fā)“個(gè)人中心”Page的onShow函數(shù),但是不會(huì)觸發(fā)onLoad函數(shù))
-
如果當(dāng)前是A場(chǎng)景,上一個(gè)是B場(chǎng)景,則清空原來的頁面棧,打開首頁(即執(zhí)行 wx.reLaunch 到首頁)如分享出去的卡片是“學(xué)員列表”頁面,點(diǎn)擊卡片停留后退出,再從首頁下拉的小程序進(jìn)入,此時(shí)會(huì)跳轉(zhuǎn)到首頁
-
不管上一個(gè)場(chǎng)景是什么,如果當(dāng)前是B場(chǎng)景,如點(diǎn)擊小程序的分享卡片,此時(shí)會(huì)清空原來的頁面棧,重新進(jìn)入這個(gè)分享頁,首先觸發(fā)app中的onShow函數(shù),然后觸發(fā)這個(gè)分享頁的onLoad函數(shù),當(dāng)然如果app中已經(jīng)進(jìn)行了跳轉(zhuǎn)到其它頁面,則不會(huì)再走這個(gè)分享頁。
-
冷啟動(dòng)場(chǎng)景效果:
-
冷啟動(dòng)規(guī)則比較簡單,如果冷啟動(dòng)時(shí)是A場(chǎng)景,則進(jìn)入小程序首頁
-
如果冷啟動(dòng)時(shí)是B場(chǎng)景,則進(jìn)入對(duì)應(yīng)的特定頁面
更新機(jī)制
-
小程序首先會(huì)在后臺(tái)有一個(gè)最新版本,一般來說會(huì)在24小時(shí)內(nèi)下發(fā)新版本信息到用戶,靜默更新到新版本(此時(shí)用戶是無感知態(tài))
-
在后臺(tái)還沒及時(shí)更新版本時(shí),每次冷啟動(dòng)都會(huì)檢測(cè)是否有更新版本,如果有,會(huì) 異步下載 ,同時(shí)啟動(dòng)當(dāng)前的舊版本包,所以新版本需要下一次的冷啟動(dòng)才會(huì)應(yīng)用上
-
如果啟動(dòng)時(shí)就想立刻獲取最新版本,需要使用 wx.getUpdateManager 的API,用wx.showModal提示用戶是否重啟應(yīng)用更新
ES6的支持情況:
-
微信小程序已經(jīng)支持了絕大部分的 ES6 API,但部分API仍依賴于系統(tǒng)版本而不支持
-
String的normalize在ios8,ios9不支持
-
數(shù)組的values在ios8和android不支持
-
數(shù)組的includes在ios8不支持
-
Proxy不支持ios8、ios9和android
注冊(cè)小程序
-
app.js中注冊(cè)小程序,整個(gè)小程序只有一個(gè) App 實(shí)例,是全部頁面共享的。
-
開發(fā)者可以通過 getApp 方法獲取到全局唯一的 App 示例,獲取App上的數(shù)據(jù)或調(diào)用開發(fā)者注冊(cè)在 App 上的函數(shù)
-
在app.js中可以直接使用this.globalData賦值,但在其他頁面需通過getApp()方法獲取到實(shí)例后才能使用全局變量globalData
App({
onLaunch: function(options) {},
onShow: function(options) {},
onHide: function() {},
onError: function(msg) {},
globalData: 'I am global data'
})
復(fù)制代碼
注冊(cè)頁面和自定義組件
頁面
-
data 是頁面第一次渲染使用的初始數(shù)據(jù)
-
onLoad頁面加載時(shí)觸發(fā)。一個(gè)頁面只會(huì)調(diào)用一次;
-
onShow在頁面顯示/切入前臺(tái)時(shí)觸發(fā)
-
onPageScroll,監(jiān)聽用戶滑動(dòng)頁面事件,( 請(qǐng)避免在 onPageScroll 中過于頻繁的執(zhí)行 setData 等引起邏輯層-渲染層通信的操作。尤其是每次傳輸大量數(shù)據(jù),會(huì)影響通信耗時(shí) )
-
onShareAppMessage監(jiān)聽頁面內(nèi)的轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)有button 組件 open-type="share"和右上角轉(zhuǎn)發(fā)兩個(gè)方式,(只有Page中定義了onShareAppMessage,右上角才會(huì)出現(xiàn)轉(zhuǎn)發(fā)功能)
-
setData:
-
將數(shù)據(jù)從邏輯層發(fā)送到視圖層(異步),同時(shí)改變對(duì)應(yīng)的 this.data 的值(同步)(跟react的setState類似,但又不一樣)
-
直接修改 this.data 而不調(diào)用 this.setData 是無法改變頁面的狀態(tài)的,還會(huì)造成數(shù)據(jù)不一致
-
不要把 data 中任何一項(xiàng)的 value 設(shè)為 undefined
-
如果需要視圖層更新完畢后再處理事件,可以將事件放在setData的回調(diào)函數(shù)中
Page構(gòu)造器:
Page({
data: { text: "This is page data." },
onLoad: function(options) { },
onReady: function() { },
onShow: function() { },
onHide: function() { },
onUnload: function() { },
onPullDownRefresh: function() { },
onReachBottom: function() { },
onShareAppMessage: function () { },
onPageScroll: function() { }
})
復(fù)制代碼
自定義組件
-
頁面使用自定義組件時(shí)需要現(xiàn)在page的json文件中聲明usingComponents定義段
-
組件使用頁面的生命周期方法時(shí)(即 on 開頭的方法),應(yīng)該寫在methods定義段中
-
behaviors 提取所有頁面中公用的代碼段,例如, 在所有頁面被創(chuàng)建和銷毀時(shí)都要執(zhí)行同一段代碼,就可以把這段代碼提取到 behaviors 中
// page-common-behavior.js
module.exports = Behavior({
attached: function() {
// 頁面創(chuàng)建時(shí)執(zhí)行
console.info('Page loaded!')
},
detached: function() {
// 頁面銷毀時(shí)執(zhí)行
console.info('Page unloaded!')
}
})
// 頁面 A
var pageCommonBehavior = require('./page-common-behavior')
Component({
behaviors: [pageCommonBehavior],
data: { /* ... */ },
methods: { /* ... */ },
})
// 頁面 B
var pageCommonBehavior = require('./page-common-behavior')
Component({
behaviors: [pageCommonBehavior],
data: { /* ... */ },
methods: { /* ... */ },
})
復(fù)制代碼
-
在 properties 定義段中,屬性名采用駝峰寫法(propertyName);在 wxml 中,指定屬性值時(shí)則對(duì)應(yīng)使用連字符寫法(component-tag-name property-name="attr value"),應(yīng)用于數(shù)據(jù)綁定時(shí)采用駝峰寫法(attr="")
-
observers數(shù)據(jù)監(jiān)聽器,(類似于vue中的watch),具體請(qǐng)參考 數(shù)據(jù)監(jiān)聽器
-
created,組件實(shí)例剛被創(chuàng)建,( 注意此時(shí)不能調(diào)用 setData )
-
definitionFilter,定義段過濾器,用于自定義組件擴(kuò)展(如擴(kuò)展自定義組件一個(gè)computed計(jì)算屬性功能)
注意:
-
使用 this.data 可以獲取內(nèi)部數(shù)據(jù)和屬性值;但直接修改它不會(huì)將變更應(yīng)用到界面上,應(yīng)使用 setData 修改
-
生命周期函數(shù)無法在組件方法中通過 this 訪問到
組件間的通信與事件
-
父傳子:父組件綁定屬性值,子組件通過properties獲取,
-
子組件向父組件傳遞數(shù)據(jù):使用事件傳遞
-
父組件訪問子組件: 父組件可以通過 this.selectComponent 方法獲取子組件實(shí)例對(duì)象,這樣就可以直接訪問組件的任意數(shù)據(jù)和方法
此處列舉第二種自定義事件傳遞數(shù)據(jù)的方法:
// 1. 父組件中監(jiān)聽事件
<component-tag-name bindmyevent="onMyEvent" />
// 2. 子組件觸發(fā)事件,觸發(fā)wxml的onMyEvent事件,觸發(fā)父組件的方法
<!--自定義組件中-->
<button bindtap="onTap">點(diǎn)擊這個(gè)按鈕將觸發(fā)“myevent”事件</button>
<!--自定義組件js文件中-->
Component({
properties: {},
methods: {
onTap: function(){
var myEventDetail = {} // detail對(duì)象,提供給事件監(jiān)聽函數(shù)
var myEventOption = {} // 觸發(fā)事件的選項(xiàng)
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
})
復(fù)制代碼
具體可參考文檔: 組件間通信與事件
注意:
-
組件和引用組件的頁面不能使用id選擇器(#a)、屬性選擇器([a])和標(biāo)簽名選擇器,請(qǐng)改用class選擇器
-
避免使用后代選擇器(.a .b)
-
子元素選擇器(.a>.b)只能用于 view 組件與其子節(jié)點(diǎn)之間,用于其他組件可能導(dǎo)致非預(yù)期的情況
-
app.wxss 中的樣式、組件所在頁面的的樣式對(duì)自定義組件無效(除繼承樣式外,如 font 、 color會(huì)繼承自組件外)
組件間關(guān)系
場(chǎng)景: 如果一個(gè)頁面中需要使用到A組件和B組件,而A組件與B組件之間需要通信,此時(shí)可以在組件定義時(shí)加入relations定義段,如封裝的ul和li組件后,之間需要存在關(guān)聯(lián)的父子關(guān)系
-
必須在兩個(gè)組件定義中都加入relations定義,否則不會(huì)生效
-
type,與目標(biāo)組件的相對(duì)關(guān)系,可選的值為 parent 、 child 、 ancestor 、 descendant
-
另一種情況是關(guān)聯(lián)一類組件(如form與input、checkbox等的關(guān)系),需要使用到behavior
具體使用方式參見 組件間關(guān)系
使用setData應(yīng)注意的事項(xiàng):
-
不要頻繁的去 setData,否則可能導(dǎo)致Android 下用戶在滑動(dòng)時(shí)會(huì)感覺到卡頓,或者渲染有出現(xiàn)延時(shí)
-
不要每次 setData 都傳遞大量新數(shù)據(jù)
-
不要在后臺(tái)態(tài)頁面進(jìn)行 setData ,
小程序運(yùn)行流程
-
微信打開小程序前,會(huì)把整個(gè)小程序的代碼包下載到本地
-
通過 app.json 的 pages 字段就可以知道你當(dāng)前小程序的所有頁面路徑
-
寫在 pages 字段的第一個(gè)頁面就是這個(gè)小程序的首頁(打開小程序看到的第一個(gè)頁面),所以微信會(huì)把首頁的代碼裝載進(jìn)來
-
小程序啟動(dòng),觸發(fā)app.js 定義的 App 實(shí)例的 onLaunch回調(diào),啟動(dòng)時(shí)也會(huì)觸發(fā)onShow函數(shù),或切前臺(tái)、從其他頁面返回到這個(gè)頁面,都會(huì)觸發(fā)onShow;onHide監(jiān)聽小程序切后臺(tái),(如tab切換,navigateTo,離開微信等); onPageNotFound頁面不存在監(jiān)聽函數(shù)
-
頁面的渲染流程開始,微信客戶端會(huì)先根據(jù) page的json文件配置生成一個(gè)界面,
-
接著裝載這個(gè)頁面的 WXML 結(jié)構(gòu)和 WXSS 樣式
-
最后客戶端會(huì)裝載 page的js文件
-
Page構(gòu)造器會(huì)生成一個(gè)頁面,生成頁面的時(shí)候小程序框架會(huì)把 data 數(shù)據(jù)和 index.wxml 一起渲染出最終的結(jié)構(gòu),渲染完界面
-
渲染完界面之后,頁面實(shí)例就會(huì)收到一個(gè) onLoad 的回調(diào)
生命周期函數(shù)
小程序里面又三種生命周期:小程序運(yùn)行的生命周期(在app.js中處理),頁面的生命周期(在page的js文件中處理,或者組件的pageLifetimes觸發(fā)的生命周期函數(shù)),組件的生命周期
小程序生命周期函數(shù)
-
onLaunch, 小程序初始化完成時(shí)觸發(fā),全局只觸發(fā)一次
-
onShow,小程序啟動(dòng),或從后臺(tái)進(jìn)入前臺(tái)顯示時(shí)觸發(fā)
-
onHide,從前臺(tái)進(jìn)入后臺(tái)時(shí)觸發(fā)
-
onError,小程序發(fā)生腳本錯(cuò)誤或 API 調(diào)用報(bào)錯(cuò)時(shí)觸發(fā)
-
onPageNotFound,小程序要打開的頁面不存在時(shí)觸發(fā)
onLaunch,onShow參數(shù):
-
path: 打開小程序的頁面路徑
-
query: 打開小程序的頁面參數(shù)query
-
scene: 打開小程序的場(chǎng)景值,
-
shareTicket: 轉(zhuǎn)發(fā)分享參數(shù)
-
referrerInfo:當(dāng)場(chǎng)景為由從另一個(gè)小程序或公眾號(hào)或App打開時(shí),返回此字段
-
referrerInfo.appId: 來源小程序或公眾號(hào)或App的 appId
-
referrerInfo.extraData: 來源小程序傳過來的數(shù)據(jù),scene=1037或1038時(shí)支持
頁面生命周期函數(shù)
-
onLoad,監(jiān)聽頁面加載
-
onShow, 監(jiān)聽頁面顯示(如tab切換或者離開微信、或navigateTo)
-
onReady, 監(jiān)聽頁面初次渲染完成(一個(gè)頁面只會(huì)調(diào)用一次,代表頁面已經(jīng)準(zhǔn)備妥當(dāng))
-
onHide, 監(jiān)聽頁面隱藏, (如 wx.navigateTo 或底部 tab 切換到其他頁面,小程序切入后臺(tái)等)
-
onUnload, 監(jiān)聽頁面卸載(如wx.redirectTo或wx.navigateBack到其他頁面時(shí))
組件生命周期函數(shù)
-
created,在組件實(shí)例剛剛被創(chuàng)建時(shí)執(zhí)行,注意此時(shí)不能調(diào)用 setData
-
attached,在組件實(shí)例進(jìn)入頁面節(jié)點(diǎn)樹時(shí)執(zhí)行
-
ready,在組件布局完成后執(zhí)行
-
moved, 在組件實(shí)例被移動(dòng)到節(jié)點(diǎn)樹另一個(gè)位置時(shí)執(zhí)行
-
detached, 在組件實(shí)例被從頁面節(jié)點(diǎn)樹移除時(shí)執(zhí)行
注意:
組件中存在一個(gè)組件所在頁面的生命周期,定義在pageLifetimes中,其中可用的生命周期包括:
-
show, 組件所在的頁面被展示時(shí)執(zhí)行
-
hide, 組件所在的頁面被隱藏時(shí)執(zhí)行
-
resize, 組件所在的頁面尺寸變化時(shí)執(zhí)行
網(wǎng)絡(luò)
-
服務(wù)器域名配置,當(dāng)使用體驗(yàn)版或者開發(fā)版報(bào)“服務(wù)器開小差”了的錯(cuò)誤,大部分可能性都是因?yàn)闆]有打開調(diào)試,因?yàn)樵谡{(diào)試模式下,小程序不會(huì)去校驗(yàn)域名的合法性。
-
小程序只可以跟指定的域名與進(jìn)行網(wǎng)絡(luò)通信,包括普通 HTTPS 請(qǐng)求(wx.request)、上傳文件(wx.uploadFile)、下載文件(wx.downloadFile) 和 WebSocket 通信(wx.connectSocket)
-
如果接入第三方網(wǎng)頁,使用web-view組件,需要配置業(yè)務(wù)域名
-
默認(rèn)超時(shí)時(shí)間為60s,超時(shí)時(shí)間可以在 app.json 或 game.json 中通過 networktimeout 配置
-
并發(fā)限制:wx.request、wx.uploadFile、wx.downloadFile 的最大并發(fā)限制是 10 個(gè);wx.connectSockt 的最大并發(fā)限制是 5 個(gè)
-
返回狀態(tài),只要成功接收到服務(wù)器返回, 無論 statusCode 是多少,都會(huì)進(jìn)入 success 回調(diào)
自定義tabBar
用戶可以通過配置app.json 中的 tabBar 項(xiàng)指定 custom 字段為true,來自定義tabBar,不過有些使用地方還需要注意:
-
tabBar 的相關(guān)配置項(xiàng)仍然需完整聲明,以兼容低版本以及區(qū)分哪些是tab頁
-
需要用戶自定義一個(gè)組件來渲染 tabBar,推薦用 fixed 在底部的 cover-view + cover-image 組件渲染樣式,以保證 tabBar 層級(jí)相對(duì)較高
-
與 tabBar 樣式相關(guān)的接口,如 wx.setTabBarItem 等將失效
-
可以在自定義組件下通過 getTabBar 接口,獲取當(dāng)前頁面的自定義 tabBar 組件實(shí)例
小程序登錄流程
小程序登錄需要調(diào)用微信的開放接口,整體流程如下:
-
小程序通過wx.login()獲取一個(gè)code
-
調(diào)用后端的api,發(fā)送code,后端通過這個(gè)code來校驗(yàn)接口,并返回一個(gè)自定義登錄態(tài)
-
小程序?qū)⒌卿洜顟B(tài)存入storage
-
之后再訪問服務(wù)器發(fā)送業(yè)務(wù)請(qǐng)求就只用后端判斷登錄態(tài)查詢openid和session_key返回業(yè)務(wù)數(shù)據(jù)
小程序優(yōu)化操作
-
縮短白屏?xí)r間:
-
首屏渲染的內(nèi)容較多,需要集合多份數(shù)據(jù)進(jìn)行渲染:此時(shí)可以把優(yōu)先級(jí)高的內(nèi)容做優(yōu)先展示
-
首屏內(nèi)容依賴的數(shù)據(jù)從服務(wù)端請(qǐng)求的時(shí)間太長:分析數(shù)據(jù)返回的時(shí)間長的原因
-
一次性渲染數(shù)據(jù)太大或依賴的計(jì)算過于復(fù)雜:減少渲染的數(shù)據(jù)量、優(yōu)化渲染相關(guān)數(shù)據(jù)的算法
-
渲染界面的耗時(shí)過長,需要校驗(yàn)下是否同時(shí)渲染的區(qū)域太大(例如列表過長)
-
腳本執(zhí)行時(shí)間過長:需要確認(rèn)并優(yōu)化腳本的邏輯
-
setData調(diào)用頻繁:避免無用的頻繁調(diào)用,每秒調(diào)用setData的次數(shù)不超過 20 次,
// 不要頻繁調(diào)用setData
this.setData({ a: 1 })
this.setData({ b: 2 })
// 絕大多數(shù)時(shí)候可優(yōu)化為
this.setData({ a: 1, b: 2 })
復(fù)制代碼
-
setData的數(shù)據(jù)太大,setData的數(shù)據(jù)在JSON.stringify后不超過 256KB
-
setData一個(gè)未綁定的變量
// 不要設(shè)置不在界面渲染時(shí)使用的數(shù)據(jù),并將界面無關(guān)的數(shù)據(jù)放在data外
this.setData({
myData: {
a: '這個(gè)字符串在WXML中用到了',
b: '這個(gè)字符串未在WXML中用到,而且它很長…………………………'
}
})
// 可以優(yōu)化為
this.setData({
'myData.a': '這個(gè)字符串在WXML中用到了'
})
this._myData = {
b: '這個(gè)字符串未在WXML中用到,而且它很長…………………………'
}
復(fù)制代碼
-
開啟 HTTP 緩存控制
-
控制WXML節(jié)點(diǎn)數(shù)
<view data-my-data="{{myData}}"> <!-- 這個(gè) view 和下一行的 view 可以合并 -->
<view class="my-class" data-my-data="{{myData}}" bindtap="onTap">
<text> <!-- 這個(gè) text 通常是沒必要的 -->
{{myText}}
</text>
</view>
</view>
<!-- 可以簡化為 -->
<view class="my-class" data-my-data="{{myData}}" bindtap="onTap">
{{myText}}
</view>
復(fù)制代碼
-
控制圖片大小,圖片寬高都不超過實(shí)際顯示寬高的3倍
-
合理控制網(wǎng)絡(luò)請(qǐng)求數(shù)量
-
控制圖片請(qǐng)求數(shù)
-
開啟慣性滾動(dòng):wxss中帶有overflow: scroll的元素,在 iOS 下需要設(shè)置-webkit-overflow-scrolling: touch樣式
-
避免使用:active偽類來實(shí)現(xiàn)點(diǎn)擊態(tài)
-
保持圖片大小比例
-
可點(diǎn)擊元素的寬高都不小于 20px
-
iphoneX兼容,用以下wxss進(jìn)行兼容:
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
復(fù)制代碼
-
避免JS異常
-
不使用廢棄接口
-
設(shè)置最低基礎(chǔ)庫版本
-
移除不可訪問到的頁面
-
移除大量未使用的樣式
-
及時(shí)回收定時(shí)器:定時(shí)器是全局的,并不是跟頁面綁定的,當(dāng)小程序從一個(gè)頁面路由到另一個(gè)頁面之后,前一個(gè)頁面定時(shí)器應(yīng)注意手動(dòng)回收