這裏主要記錄這段時間開發小程序過程當中遇到的坑和要注意的點。主要是但願在之後開發小程序的過程當中能在評審需求的時候就發現哪些能實現,哪些實現起來比較困難。這樣就能在定設計和交互以前儘量的減小後期踩坑的風險。javascript
微信自帶的下拉刷新須要在配置中開啓:html
app.json
中的 window
或者單個頁面的json
文件屬性 | 類型 | 默認值 | 描述 |
---|---|---|---|
backgroundTextStyle | string | dark | 下拉 loading 的樣式,僅支持 dark / light |
enablePullDownRefresh | boolean | false | true 開啓 false關閉 |
onPullDownRefresh
方法監聽下拉動做onPullDownRefresh() {
setTimeout(() => {
wx.stopPullDownRefresh()
}, 1000)
}
複製代碼
這裏有個要注意的問題:
在onPullDownRefresh
中不能調用wx.startPullDownRefresh()
,不然會死循環java
自定義的下拉刷新,目前只支持整個頁面的下拉刷新,對於局部的下拉刷新,就沒有辦法了:android
局部的下拉刷新ios
這種咱們可使用自定義下拉刷新的方式來實現。詳細的能夠看個人另外一篇博客,這裏也就不贅述了。web
navigationBar
小程序自帶的navigationBar
僅能夠在json
文件中配置。提供的可配置項也是少的可憐。主要以下:chrome
屬性 | 類型 | 默認值 | 描述 |
---|---|---|---|
navigationBarBackgroundColor | HexColor | #000000 | 導航欄標題文字內容 |
navigationBarTextStyle | string | white | 導航欄標題顏色,僅支持 black / white |
navigationBarTitleText | string | 導航欄標題文字內容 |
從上面的表格能夠看出來,頂部導航欄樣式固定,咱們僅能夠修改文字,字體顏色和背景色。json
不過還好小程序還提供了自定義頂部導航的配置,window.navigationStyle
,這個配置項支持兩個值default|custom
。默認是default
,表示的是用小程序自帶的導航欄,配置爲custom
時是自定義導航欄,其實就是小程序隱藏掉導航欄,而後咱們本身實現。canvas
可是自定義導航欄不只帶來了設計上的自由,也帶來了不少坑。小程序
不一樣於web
開發,小程序和app
對於下拉刷新的需求很是的多,也算是基本功能之一,小程序自己也自帶下拉刷新。咱們只需將window.enablePullDownRefresh
設置爲true
,而後在頁面監聽onPullDownRefresh
便可。
可是當咱們用到自定義navigationBar
的時候,會發現,原本fixed
定位在頂端的navigationBar
會被一塊兒拉下來。
系統自帶的navigationBar的下拉刷新
自定義navigationBar的下拉刷新
這個時候咱們就必需要使用自定義的下拉刷新。關於自定義的下拉刷新的實現原理這裏就很少說了。可是實現起來在真機中發現,android
手機會有明顯的卡頓。
按照正常的navigationBar
,通常這個組件的層級是最高,僅次於遮罩層和彈窗這些組件。通常的組件可使用z-index
屬性來控制層級。
可是小程序中有種概念叫作:原生組件
這些組件包括camera
,canvas
,input
(僅在focus時表現爲原生組件),map
,textarea
,video
,live-player
,live-pusher
這種組件脫離於WebView渲染流程以外,層級也是最高的,所以不管z-index
設置多大,都沒法覆蓋原生組件。
系統自帶的navigationBar
自定義navigationBar
雖然理論上咱們能夠用cover-view
和cover-image
來實現自定義的navigationBar
,可是我的以爲仍是儘可能避免使用自定義的navigationBar
。
雖然
cover-view
和cover-image
組件能夠覆蓋在部分原生組件上面。對於原生組件之間,可使用z-index
來控制他們的層級。可是小程序
cover-view
組件內部只支持嵌套cover-view
和cover-image
以及button
。這在很大程度上不支持咱們做出多麼有個性化的組件。並且實現起來坑也不少。並且關於用
z-index
來控制層級這點也存疑,雖然文檔上這樣說明,可是,我在開發中發現,實際上仍是看渲染的順序。後渲染的始終在先渲染的上層。
這個是針對textarea
組件在頁面底部的時候,準確來講是textarea
組件距離底部的距離沒有鍵盤高的時候。在鍵盤彈起時形成了整個頁面上移,從而致使了導航欄會移到頁面外。
當鍵盤未彈起時
當鍵盤彈起時
固然這個不算是硬傷,畢竟出現的條件有限,咱們能夠在設計上儘可能避免將textarea
放到底部來避免這個坑。
tabbar
tabbar
在說自定義以前先看看小程序自帶的tabbar
能夠作到什麼程度。
自定義的tabbar
是在app.json
中配置的,在tabBar
下:
屬性 | 類型 | 描述 |
---|---|---|
color | HexColor | tab 上的文字默認顏色,僅支持十六進制顏色 |
selectedColor | HexColor | tab 上的文字選中時的顏色,僅支持十六進制顏色 |
backgroundColor | HexColor | tab 的背景色,僅支持十六進制顏色 |
borderStyle | string | tabbar上邊框的顏色, 僅支持 black / white |
list | Array | tab 的列表,詳見 list 屬性說明,最少2個、最多5個 tab |
position | string | tabBar的位置,僅支持 bottom / top |
custom | boolean | 自定義 tabBar,見詳情 |
list
選項配置屬性 | 類型 | 描述 |
---|---|---|
pagePath | string | 頁面路徑,必須在 pages 中先定義 |
text | string | tab 上按鈕文字 |
iconPath | string | 圖片路徑,icon 大小限制爲40kb,建議尺寸爲 81px * 81px,不支持網絡圖片。當 position 爲 top 時,不顯示 icon。 |
selectedIconPath | string | 選中時的圖片路徑,icon 大小限制爲40kb,建議尺寸爲 81px * 81px,不支持網絡圖片。當 position 爲 top 時,不顯示 icon。 |
因此從上面咱們能夠看到,咱們能夠定義tabbar
的選中和未選中圖標和字體顏色。沒辦法加入別的樣式和嵌入別的自定義點擊事件。
這是比較老的版本的形式。在須要tabbar
的頁面嵌入tabbar
組件。這是最簡單的實現方式。可是在首次切換的時候,會有很明顯的閃屏。
這個比第一種要好點,也是我在項目中用到的一種模式,可是切換的時候也有稍微的閃屏
tabbar
的形勢這種實現方式稍微複雜,也就是將首頁的幾個頁面做爲組件傳入,經過路由控制頁面切換。
之因此叫僞tabbar
的形勢,是由於這個只是表面上是tabbar
。
理論上這種方式實現的在切換的時候能夠作到不閃屏。可是會不會帶來別的問題呢?
好比說返回的時候會不會形成頁面錯亂?
本來的頁面生命週期和組件的生命週期略有不一樣,會不會形成一些坑?
還有個幾乎能夠確定的問題,就是若是不使用cover-view
的話,咱們就無法蓋住原生組件。
不過好在小程序組件和頁面之間的切換很方便,特別是在用Taro
以後,組件和頁面的區分僅僅只是是否在app.tsx
中註冊。因此第二和第三種實現方式切換起來並非很麻煩。可是目前看來的話第二種實現方式體驗還算滿意,所以也沒有必要切換到第三種方式。
額,其實我說的這三個,幾乎能夠總結出一個問題,那就是小程序中讓人吐血的層級問題。
其實不管是彈窗仍是navigation
仍是tabbar
他們都有一個特色,就是定位在頁面的某一個位置,還有層級要足夠高,要可以覆蓋住底層元素。
官方沒有專門的彈窗容器(我以爲應該有一個彈窗容器)所以只能靠咱們本身寫了。可是由於cover-view
使人蛋疼的樣式支持度,我的以爲僅僅用cover-view
和cover-image
來實現一個定製化的彈窗幾乎不可能。
若是不用cover-view
你會發現不少經常使用的組件都是騎在你臉上,而你毫無辦法的。
所以我的建議,在有原生組件的頁面上,儘可能避免彈層的出現。
若是是在沒法妥協,那也建議彈窗組件分兩塊來寫,一種專門用cover-view
和cover-image
來寫,而且必定要寫z-index
來控制層級,理論上是後面的元素會覆蓋在上一個元素上面,可是仍是要防止有些組件在操做的過程當中從新渲染,而改變原有的層級。而對於頁面中沒有原生組件的,能夠用view
來寫,這樣樣式上就自由不少。
關於富文本的渲染。如今基本的作法都是先把html
解析爲節點信息,而後再經過模板渲染爲wxml
。可是由於小程序模板不支持遞歸調用。因此在不少第三方組件中都出現如下的代碼:
<!--temp0-->
<template>
...
<template is="temp1"></template>
</template>
<!--temp1-->
<template>
...
<template is="temp2"></template>
</template>
<!--temp2-->
<template>
...
<template is="temp3"></template>
</template>
...
複製代碼
一般這種代碼會出現十幾到二十幾個,也就是說最多支持嵌套二十多層。若是不夠的話就得本身加了。我就遇到過一個富文本,足足嵌套到了兩百多層。我複製到一百的時候實在受不了了,寫了一個模板生成器來完成。
網上有人說這種代碼看起來蠢哭了。的確,可是也很無奈。
這個不能說是小程序的坑,應該說是ios和android對new Date()
處理上的差別。咱們能夠用safari
瀏覽器和chrome
來複現這兩種差別
咱們公司先後端交互用的時間格式是YYYY-MM-DDTHH:mm:ss
。這種格式的時間字符串用new Date()
來處理,在safari
和chrome
的表現以下:
new Date('2019-05-29T14:00:00')
// safari Wed May 29 2019 22:00:00 GMT+0800 (CST) = $2
// chrome Wed May 29 2019 14:00:00 GMT+0800 (中國標準時間)
複製代碼
safari
是比chrome
要早8小時的,這是由於chrome
認爲這個時間是本地時間,而safari
認爲是國際標準時間,因此會有這樣的8小時差別(僅限於中國)。
所以在調用new Date()
以前咱們須要把YYYY-MM-DDTHH:mm:ss
格式的轉換爲YYYY/MM/DD HH:mm:ss
這種格式的字符串。
此外,我在處理的過程當中還發現帶毫秒數的事件字符串2019-05-29T14:00:00.000
,這種的還須要將毫秒數去掉變成這種格式2019/05/29 14:00:00
。而後在ios
和android
上表現也就一致了。
function getDate(date: any) {
if(typeof date === 'string') {
return new Date(date.replace('T', ' ').replace(/\-/g, '/').split('.')[0])
}
return new Date(date)
}
複製代碼
小程序在android
下,字體的font-weight
必需要設置到700
及以上纔會變粗,或者統一使用bold
ios
android
小程序大小是有限制的,目前是主包不超過2M。但是爲了實現一些功能,致使咱們很容易就超過了這個限制。
好在官方提供了分包方式。具體能夠參照官方文檔。
就一點:對於副包內引用的,較大的包,應該包含在分包的文件夾內部。否則仍然會打包在主包內部
px
和rpx
rpx
來作適配最近在作一個需求,以爲有個點仍是須要注意的,特此記錄一下。
這個需求就是一個簡單的消息輪播。以下圖:
就是紅框區域的一個向下無限滾動輪播,時間間隔爲2s
。我是使用translateY
來實現的。每次translateY
的高度和消息塊的高度相同。
可是在滾動的過程當中,發如今某些機型上面每次滾動都會有細微的偏移,而在某些機型上面正常。
消息顯示窗口的高度和每一個消息的高度都是80rpx
。代碼以下:
<View className="notice-pannel" style={{transform: `translateY(${curIndex * -80}rpx)`, transition}}>
{
list.map(item => (
<View className="notice-item" key={item.id}>
<Image className="notice-avatar" src={item.actor.avatar_url}></Image>
<Text className="notice-desc">{`${item.actor.login} ${item.payload.action} ${item.repo.name} at ${new DateX(item.created_at).format()}`}</Text>
</View>
))
}
</View>
複製代碼
最後定位問題的緣由是由於部分屏幕寬度在換算rpx
的時候會有偏差,致使每次translateY
的時候會有一個小偏差。
rpx
根據官方文檔的定義是:rpx(responsive pixel): 能夠根據屏幕寬度進行自適應。規定屏幕寬爲750rpx。
所以,會有些屏幕寬度在rpx轉px的時候會有除不盡的時候,這時候每每會有四捨五入取整的狀況。
在看這行代碼${curIndex * -80}rpx)
,假設咱們的設備的屏幕寬度爲412
這時候80rpx
專成px
的時候是43.946666666666665px
。開發者工具上會發現,其實是換算成了43
,也就是每一個消息塊的高度是43px
。
當curIndex
爲2
的時候,實際上咱們應該偏移43 * 2
也就是86px
,但是若是是直接用rpx
的話,咱們發現會是87px
。這時候就產生了偏移了。
知道緣由的話解決方案也有了,就是用px
作單位就能夠了
<View className="notice-pannel" style={{transform: `translateY(${curIndex * rpx2px(-80)}rpx)`, transition}}>
{
list.map(item => (
<View className="notice-item" key={item.id}>
<Image className="notice-avatar" src={item.actor.avatar_url}></Image>
<Text className="notice-desc">{`${item.actor.login} ${item.payload.action} ${item.repo.name} at ${new DateX(item.created_at).format()}`}</Text>
</View>
))
}
</View>
複製代碼