小程序开发日记
這里主要記錄這段時(shí)間開(kāi)發(fā)小程序過(guò)程中遇到的坑和要注意的點(diǎn)。主要是希望在以后開(kāi)發(fā)小程序的過(guò)程中能在評(píng)審需求的時(shí)候就發(fā)現(xiàn)哪些能實(shí)現(xiàn),哪些實(shí)現(xiàn)起來(lái)比較困難。這樣就能在定設(shè)計(jì)和交互之前盡可能的減少后期踩坑的風(fēng)險(xiǎn)。
下拉刷新
自定義的下拉刷新
微信自帶的下拉刷新需要在配置中開(kāi)啟:
| backgroundTextStyle | string | dark | 下拉 loading 的樣式,僅支持 dark / light |
| enablePullDownRefresh | boolean | false | true 開(kāi)啟 false關(guān)閉 |
這里有個(gè)要注意的問(wèn)題:
在onPullDownRefresh中不能調(diào)用wx.startPullDownRefresh(),否則會(huì)死循環(huán)
自定義的下拉刷新,目前只支持整個(gè)頁(yè)面的下拉刷新,對(duì)于局部的下拉刷新,就沒(méi)有辦法了:
局部的下拉刷新
這種我們可以使用自定義下拉刷新的方式來(lái)實(shí)現(xiàn)。詳細(xì)的可以看我的另一篇博客,這里也就不贅述了。
關(guān)于自定義頂部navigationBar
小程序自帶的navigationBar僅可以在json文件中配置。提供的可配置項(xiàng)也是少的可憐。主要如下:
| navigationBarBackgroundColor | HexColor | #000000 | 導(dǎo)航欄標(biāo)題文字內(nèi)容 |
| navigationBarTextStyle | string | white | 導(dǎo)航欄標(biāo)題顏色,僅支持 black / white |
| navigationBarTitleText | string | 導(dǎo)航欄標(biāo)題文字內(nèi)容 |
從上面的表格可以看出來(lái),頂部導(dǎo)航欄樣式固定,我們僅可以修改文字,字體顏色和背景色。
不過(guò)還好小程序還提供了自定義頂部導(dǎo)航的配置,window.navigationStyle,這個(gè)配置項(xiàng)支持兩個(gè)值default|custom。默認(rèn)是default,表示的是用小程序自帶的導(dǎo)航欄,配置為custom時(shí)是自定義導(dǎo)航欄,其實(shí)就是小程序隱藏掉導(dǎo)航欄,然后我們自己實(shí)現(xiàn)。
但是自定義導(dǎo)航欄不僅帶來(lái)了設(shè)計(jì)上的自由,也帶來(lái)了很多坑。
下拉刷新
不同于web開(kāi)發(fā),小程序和app對(duì)于下拉刷新的需求非常的多,也算是基本功能之一,小程序本身也自帶下拉刷新。我們只需將window.enablePullDownRefresh設(shè)置為true,然后在頁(yè)面監(jiān)聽(tīng)onPullDownRefresh即可。
但是當(dāng)我們用到自定義navigationBar的時(shí)候,會(huì)發(fā)現(xiàn),本來(lái)fixed定位在頂端的navigationBar會(huì)被一起拉下來(lái)。
系統(tǒng)自帶的navigationBar的下拉刷新
自定義navigationBar的下拉刷新
這個(gè)時(shí)候我們就必須要使用自定義的下拉刷新。關(guān)于自定義的下拉刷新的實(shí)現(xiàn)原理這里就不多說(shuō)了。但是實(shí)現(xiàn)起來(lái)在真機(jī)中發(fā)現(xiàn),android手機(jī)會(huì)有明顯的卡頓。
層級(jí)問(wèn)題
按照正常的navigationBar,一般這個(gè)組件的層級(jí)是最高,僅次于遮罩層和彈窗這些組件。一般的組件可以使用z-index屬性來(lái)控制層級(jí)。
但是小程序中有種概念叫做:原生組件
這些組件包括camera,canvas,input(僅在focus時(shí)表現(xiàn)為原生組件),map,textarea,video,live-player,live-pusher
這種組件脫離于WebView渲染流程之外,層級(jí)也是最高的,因此無(wú)論z-index設(shè)置多大,都無(wú)法覆蓋原生組件。
系統(tǒng)自帶的navigationBar
自定義navigationBar
雖然理論上我們可以用cover-view和cover-image來(lái)實(shí)現(xiàn)自定義的navigationBar,但是個(gè)人覺(jué)得還是盡量避免使用自定義的navigationBar。
雖然cover-view和cover-image組件可以覆蓋在部分原生組件上面。對(duì)于原生組件之間,可以使用z-index來(lái)控制他們的層級(jí)。
但是小程序cover-view組件內(nèi)部只支持嵌套cover-view和cover-image以及button。這在很大程度上不支持我們作出多么有個(gè)性化的組件。而且實(shí)現(xiàn)起來(lái)坑也很多。
而且關(guān)于用z-index來(lái)控制層級(jí)這點(diǎn)也存疑,雖然文檔上這樣說(shuō)明,但是,我在開(kāi)發(fā)中發(fā)現(xiàn),實(shí)際上還是看渲染的順序。后渲染的始終在先渲染的上層。
鍵盤(pán)彈起時(shí)會(huì)將頂部導(dǎo)航欄頂上去
這個(gè)是針對(duì)textarea組件在頁(yè)面底部的時(shí)候,準(zhǔn)確來(lái)說(shuō)是textarea組件距離底部的距離沒(méi)有鍵盤(pán)高的時(shí)候。在鍵盤(pán)彈起時(shí)造成了整個(gè)頁(yè)面上移,從而導(dǎo)致了導(dǎo)航欄會(huì)移到頁(yè)面外。
當(dāng)鍵盤(pán)未彈起時(shí)
當(dāng)鍵盤(pán)彈起時(shí)
當(dāng)然這個(gè)不算是硬傷,畢竟出現(xiàn)的條件有限,我們可以在設(shè)計(jì)上盡量避免將textarea放到底部來(lái)避免這個(gè)坑。
自定義底部tabbar
自定義的tabbar
在說(shuō)自定義之前先看看小程序自帶的tabbar可以做到什么程度。
自定義的tabbar是在app.json中配置的,在tabBar下:
- 基本配置
| color | HexColor | tab 上的文字默認(rèn)顏色,僅支持十六進(jìn)制顏色 |
| selectedColor | HexColor | tab 上的文字選中時(shí)的顏色,僅支持十六進(jìn)制顏色 |
| backgroundColor | HexColor | tab 的背景色,僅支持十六進(jìn)制顏色 |
| borderStyle | string | tabbar上邊框的顏色, 僅支持 black / white |
| list | Array | tab 的列表,詳見(jiàn) list 屬性說(shuō)明,最少2個(gè)、最多5個(gè) tab |
| position | string | tabBar的位置,僅支持 bottom / top |
| custom | boolean | 自定義 tabBar,見(jiàn)詳情 |
- list選項(xiàng)配置
| pagePath | string | 頁(yè)面路徑,必須在 pages 中先定義 |
| text | string | tab 上按鈕文字 |
| iconPath | string | 圖片路徑,icon 大小限制為40kb,建議尺寸為 81px * 81px,不支持網(wǎng)絡(luò)圖片。當(dāng) position 為 top 時(shí),不顯示 icon。 |
| selectedIconPath | string | 選中時(shí)的圖片路徑,icon 大小限制為40kb,建議尺寸為 81px * 81px,不支持網(wǎng)絡(luò)圖片。當(dāng) position 為 top 時(shí),不顯示 icon。 |
所以從上面我們可以看到,我們可以定義tabbar的選中和未選中圖標(biāo)和字體顏色。沒(méi)辦法加入別的樣式和嵌入別的自定義點(diǎn)擊事件。
自定義的幾種實(shí)現(xiàn)方式
這是比較老的版本的形式。在需要tabbar的頁(yè)面嵌入tabbar組件。這是最簡(jiǎn)單的實(shí)現(xiàn)方式。但是在首次切換的時(shí)候,會(huì)有很明顯的閃屏。
這個(gè)比第一種要好點(diǎn),也是我在項(xiàng)目中用到的一種模式,但是切換的時(shí)候也有稍微的閃屏
這種實(shí)現(xiàn)方式稍微復(fù)雜,也就是將首頁(yè)的幾個(gè)頁(yè)面作為組件傳入,通過(guò)路由控制頁(yè)面切換。
之所以叫偽tabbar的形勢(shì),是因?yàn)檫@個(gè)只是表面上是tabbar。
理論上這種方式實(shí)現(xiàn)的在切換的時(shí)候可以做到不閃屏。但是會(huì)不會(huì)帶來(lái)別的問(wèn)題呢?
比如說(shuō)返回的時(shí)候會(huì)不會(huì)造成頁(yè)面錯(cuò)亂?
原本的頁(yè)面生命周期和組件的生命周期略有不同,會(huì)不會(huì)造成一些坑?
還有個(gè)幾乎可以肯定的問(wèn)題,就是如果不使用cover-view的話(huà),我們就沒(méi)法蓋住原生組件。
不過(guò)好在小程序組件和頁(yè)面之間的切換很方便,特別是在用Taro之后,組件和頁(yè)面的區(qū)分僅僅只是是否在app.tsx中注冊(cè)。所以第二和第三種實(shí)現(xiàn)方式切換起來(lái)并不是很麻煩。但是目前看來(lái)的話(huà)第二種實(shí)現(xiàn)方式體驗(yàn)還算滿(mǎn)意,因此也沒(méi)有必要切換到第三種方式。
關(guān)于彈窗
額,其實(shí)我說(shuō)的這三個(gè),幾乎可以總結(jié)出一個(gè)問(wèn)題,那就是小程序中讓人吐血的層級(jí)問(wèn)題。
其實(shí)不論是彈窗還是navigation還是tabbar他們都有一個(gè)特點(diǎn),就是定位在頁(yè)面的某一個(gè)位置,還有層級(jí)要足夠高,要能夠覆蓋住底層元素。
官方?jīng)]有專(zhuān)門(mén)的彈窗容器(我覺(jué)得應(yīng)該有一個(gè)彈窗容器)因此只能靠我們自己寫(xiě)了。但是因?yàn)閏over-view令人蛋疼的樣式支持度,個(gè)人覺(jué)得僅僅用cover-view和cover-image來(lái)實(shí)現(xiàn)一個(gè)定制化的彈窗幾乎不可能。
如果不用cover-view你會(huì)發(fā)現(xiàn)很多常用的組件都是騎在你臉上,而你毫無(wú)辦法的。
因此個(gè)人建議,在有原生組件的頁(yè)面上,盡量避免彈層的出現(xiàn)。
如果是在無(wú)法妥協(xié),那也建議彈窗組件分兩塊來(lái)寫(xiě),一種專(zhuān)門(mén)用cover-view和cover-image來(lái)寫(xiě),并且一定要寫(xiě)z-index來(lái)控制層級(jí),理論上是后面的元素會(huì)覆蓋在上一個(gè)元素上面,但是還是要防止有些組件在操作的過(guò)程中重新渲染,而改變?cè)械膶蛹?jí)。而對(duì)于頁(yè)面中沒(méi)有原生組件的,可以用view來(lái)寫(xiě),這樣樣式上就自由很多。
關(guān)于html2wxml
關(guān)于富文本的渲染。現(xiàn)在基本的做法都是先把html解析為節(jié)點(diǎn)信息,然后再通過(guò)模板渲染為wxml。但是因?yàn)樾〕绦蚰0宀恢С诌f歸調(diào)用。所以在很多第三方組件中都出現(xiàn)以下的代碼:
<!--temp0--> <template> ...<template is="temp1"></template> </template> <!--temp1--> <template> ...<template is="temp2"></template> </template> <!--temp2--> <template> ...<template is="temp3"></template> </template> ... 復(fù)制代碼通常這種代碼會(huì)出現(xiàn)十幾到二十幾個(gè),也就是說(shuō)最多支持嵌套二十多層。如果不夠的話(huà)就得自己加了。我就遇到過(guò)一個(gè)富文本,足足嵌套到了兩百多層。我復(fù)制到一百的時(shí)候?qū)嵲谑懿涣肆?#xff0c;寫(xiě)了一個(gè)模板生成器來(lái)完成。
網(wǎng)上有人說(shuō)這種代碼看起來(lái)蠢哭了。的確,但是也很無(wú)奈。
時(shí)間格式化問(wèn)題
這個(gè)不能說(shuō)是小程序的坑,應(yīng)該說(shuō)是ios和android對(duì)new Date()處理上的差異。我們可以用safari瀏覽器和chrome來(lái)復(fù)現(xiàn)這兩種差異
我們公司前后端交互用的時(shí)間格式是YYYY-MM-DDTHH:mm:ss。這種格式的時(shí)間字符串用new Date()來(lái)處理,在safari和chrome的表現(xiàn)如下:
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 (中國(guó)標(biāo)準(zhǔn)時(shí)間) 復(fù)制代碼safari是比chrome要早8小時(shí)的,這是因?yàn)閏hrome認(rèn)為這個(gè)時(shí)間是本地時(shí)間,而safari認(rèn)為是國(guó)際標(biāo)準(zhǔn)時(shí)間,所以會(huì)有這樣的8小時(shí)差異(僅限于中國(guó))。
因此在調(diào)用new Date()之前我們需要把YYYY-MM-DDTHH:mm:ss格式的轉(zhuǎn)換為YYYY/MM/DD HH:mm:ss這種格式的字符串。
此外,我在處理的過(guò)程中還發(fā)現(xiàn)帶毫秒數(shù)的事件字符串2019-05-29T14:00:00.000,這種的還需要將毫秒數(shù)去掉變成這種格式2019/05/29 14:00:00。然后在ios和android上表現(xiàn)也就一致了。
function getDate(date: any) {if(typeof date === 'string') {return new Date(date.replace('T', ' ').replace(/\-/g, '/').split('.')[0])}return new Date(date) } 復(fù)制代碼字體
小程序在android下,字體的font-weight必須要設(shè)置到700及以上才會(huì)變粗,或者統(tǒng)一使用bold
ios
android
小程序分包
小程序大小是有限制的,目前是主包不超過(guò)2M。可是為了實(shí)現(xiàn)一些功能,導(dǎo)致我們很容易就超過(guò)了這個(gè)限制。
好在官方提供了分包方式。具體可以參照官方文檔。
就一點(diǎn):對(duì)于副包內(nèi)引用的,較大的包,應(yīng)該包含在分包的文件夾內(nèi)部。不然仍然會(huì)打包在主包內(nèi)部
關(guān)于px和rpx
不能無(wú)腦的全站用rpx來(lái)做適配
最近在做一個(gè)需求,覺(jué)得有個(gè)點(diǎn)還是需要注意的,特此記錄一下。
這個(gè)需求就是一個(gè)簡(jiǎn)單的消息輪播。如下圖:
就是紅框區(qū)域的一個(gè)向下無(wú)限滾動(dòng)輪播,時(shí)間間隔為2s。我是使用translateY來(lái)實(shí)現(xiàn)的。每次translateY的高度和消息塊的高度相同。
但是在滾動(dòng)的過(guò)程中,發(fā)現(xiàn)在某些機(jī)型上面每次滾動(dòng)都會(huì)有細(xì)微的偏移,而在某些機(jī)型上面正常。
消息顯示窗口的高度和每個(gè)消息的高度都是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> 復(fù)制代碼最后定位問(wèn)題的原因是因?yàn)椴糠制聊粚挾仍趽Q算rpx的時(shí)候會(huì)有誤差,導(dǎo)致每次translateY的時(shí)候會(huì)有一個(gè)小誤差。
rpx根據(jù)官方文檔的定義是:rpx(responsive pixel): 可以根據(jù)屏幕寬度進(jìn)行自適應(yīng)。規(guī)定屏幕寬為750rpx。
因此,會(huì)有些屏幕寬度在rpx轉(zhuǎn)px的時(shí)候會(huì)有除不盡的時(shí)候,這時(shí)候往往會(huì)有四舍五入取整的情況。
在看這行代碼${curIndex * -80}rpx),假設(shè)我們的設(shè)備的屏幕寬度為412這時(shí)候80rpx專(zhuān)成px的時(shí)候是43.946666666666665px。開(kāi)發(fā)者工具上會(huì)發(fā)現(xiàn),實(shí)際上是換算成了43,也就是每個(gè)消息塊的高度是43px。
當(dāng)curIndex為2的時(shí)候,實(shí)際上我們應(yīng)該偏移43 * 2也就是86px,可是如果是直接用rpx的話(huà),我們發(fā)現(xiàn)會(huì)是87px。這時(shí)候就產(chǎn)生了偏移了。
知道原因的話(huà)解決方案也有了,就是用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> 復(fù)制代碼轉(zhuǎn)載于:https://juejin.im/post/5cf4861d6fb9a07efa090237
總結(jié)
- 上一篇: 【更新链接】U盘启动制作工具(UDTOO
- 下一篇: shell date