標籤:首頁 click www. debug 位置 特性 rcu 分享 editor
一、背景
在上次和小夥伴分享了快應用(後面簡稱hap)後,有很多待定的思路沒有去嘗試。這周有時間簡單開發了一個熱門微博的應用,主要涉及到的痛點:富文本、長列表、畫廊。這裡將整個開發過程中遇到的問題以及解決思路和方法分享給大家,希望對想踩坑的各位有所協助。
代碼:https://github.com/SmileSmith/quickapp-weibo
PS:快應用目前好像還沒有發布正式版,中間會包含一些吐槽(紅字),歡迎指導和拍磚~
二、開發問題和痛點記錄1、前期準備
注意package.json中的toolkit和packager的版本號碼,表明hap工程toolkit的版本,建議執行 hap update --force更新到最新版本,支援更多特性。
"toolkit": "0.0.30","packager": "0.0.5"
例如在寫【原創】快應用QuickApp--HelloWorld體驗中,這個版本還是0.0.26,babel還不支援stage2。目前0.0.30版本已經預設支援。
執行 hap update --force會導致.babelrc和.eslintrc.json被重新整理,請注意。
2、目錄結構
因之前項目的習慣,不喜歡直接將頁面的檔案夾放在src下面,改為統一放在src/pages下,在mainfest.json修改如下
"router": { "entry": "pages/Home", "pages": { "pages/Home": { // 加上pages/ "component": "index" }, ... }, "display": { "titleBarBackgroundColor": "#e6162d", "titleBarTextColor": "#eeeeee", "menu": true, "pages": { "pages/Home": { // 加上pages/ "titleBarText": "首頁", "menu": false }, ...3、內部介面封裝
內部介面中涉及非同步作業的,大部分和小程式一樣使用 success、fail 的回調實現。為方便後續開發,用Promise簡單封裝了內部介面,並保持介面名稱與小程式一致。然後在app.ux中全域匯入$app中。
這樣,在各個頁面中就不需要反覆寫 import router from ‘@system.router‘; 或 var router = require(‘‘@system.router‘‘),直接使用this.$app.api()即可。
詳情見src/utils/mv.js、src/utils/app.ux
4、長列表使用內部組件List
請先參考官方List教程說明,注意下面的效能最佳化建議,這裡著重說明幾點:
1、List通過,對不同結構的列表元素設定不同type,對列表的元素設定唯一的tid,以實現DOM結構複用,提升滑動和渲染的效能表現
2、官方說明中使用對象池概念的memList,在資料量大的情況下會導致渲染對象List丟失,這點和小程式很像。所以本項目沒有使用memList的做法
3、目前遇到兩個問題
(a) List中的子組件使用if和for進行判斷渲染時,會重新整理不及時。即修改了if中的條件,但是介面沒有重新整理
(b)在List中嵌套for迴圈,for迴圈的子組件如果是可複用的DOM標籤,會導致DOM節點被錯誤複用。表現為,中a微博的圖片出現在b微博中。
<block for="(picIndex, pic) in backPics"> // image標籤會因為複用,混亂地出現在不同的子項目中 <image if="{{showIndex === picIndex}}" class="picture {{enterClass}}" src="{{pic}}" @swipe="changePic()"></image> </block>
<text class="gallery"> // text中的span是行元素,不會複用,在List中嵌套這樣的組件沒問題。這裡代碼只做說明,格式有問題 <block for="(picIndex, pic) in backPics"> <span if="{{showIndex === picIndex}}" class="picture {{enterClass}}" src="{{pic}}" @swipe="changePic()"></span> </block> </text>>
4、富文本
官方的rich-text支援吃快應用格式的html字串,所以微博介面返回的原生html字串中含有icon等表情,不能使用。
項目參考在小程式中的做法,先用正則過濾,並遍曆形成內容數組,然後在template中for迴圈出來。詳情見 src/components/richContent.ux
目前有個問題:
用text嵌入span和a,text中不支援image或其它形式的圖片,無法展示表情icon。
如果採用div嵌入text、a和image,又會遇到List中元素錯亂問題。
5、畫廊展示大圖
開始的做法,開發一個gallery組件,放在全域,然後通過訊息控制,然而還是遇到List渲染問題。
目前採用頁面的做法,通過路由傳參數。一是可以做到全屏,二是避開List最佳化的問題。詳情見 src/pages/Gallery/index.ux
利用stack覆蓋的特性,將小圖和載入動畫放在下面,然後等待大圖載入,大圖載入完畢後會覆蓋小圖和載入動畫。
<stack class="gallery"> <block for="(picIndex, pic) in backPics"> // 在列表中已經載入好的小圖,保證使用者能第一時間看到內容,雖然是模糊的 <image if="{{showIndex === picIndex}}" class="picture {{enterClass}}" src="{{pic}}" @swipe="changePic()"></image> </block> <progress class="load-progress" type="circular"></progress> // 載入動畫 <block for="(picIndex, pic) in showPics"> // 大圖,等待載入完畢後覆蓋小圖和動畫 <image if="{{showIndex === picIndex}}" class="picture {{enterClass}}" src="{{pic}}" @longpress="longpress" @swipe="changePic()"></image> </block> <div show="{{showIndex > 0}}" class="button left-button" @click="changePic({direction: ‘right‘})"><text>?</text></div> <div show="{{showIndex < showPics.length - 1}}" class="button right-button" @click="changePic({direction: ‘left‘})"><text>?</text></div> <div class="button back-button" @click="closeGallery"><text>︽</text></div> </stack>
目前有個問題:
統一元素不支援同時監聽click和swiper事件,所以無法實現點擊返回列表
大圖渲染問題,實測大圖在高寬比不超過螢幕時,顯示正常;超過時(如長圖片)會導致渲染模糊,越長越模糊:
5、樣式類問題
- 沒有樣式繼承,div中寫的font-size只無效的,必須寫在對應的text或span中
- justify-content 不支援 space-around,可以用容器包裹,容器padding實現。
- position只有fixed,要實現relative用padding調整位置
- border不支援border-left寫法,需要border: 0px solid #eeeeee; border-left: 1px;
5、Debugger
在調試器中點擊開始調試,在代碼中打上debugger,就能調試了。
三、總結
快應用整體還處於beat階段,許多特性還有問題,希望官方儘快解決吧。整體寫法偏向小程式,以後類似mpvue的東西應該也會出現;效能優於小程式,目前生態小,最大的問題還是推廣。。。
之前想到的幾個方向,目前還有兩個在探索中,有結果再寫吧。1)組件 √2)路由 √3)原生介面 √4)全域狀態管理:考慮繼承mobx或類似的flux組件5)類型檢測: 考慮用ts
【筆記】快應用QuickApp(hap) -- 構建一個微博應用