微信小程序調(diào)起鍵盤性能優(yōu)化
在小程序中,我們經(jīng)常有調(diào)起鍵盤的操作場景,但是在不同的場景下解決方案不盡相同,還是需要具體問題具體分析。
需求分析
最近在項目中有一個需求,是從列表頁點擊評論按鈕進入詳情頁時,在加載完頁面后自動調(diào)起鍵盤進入評論狀態(tài)。從需求來看,我們應(yīng)該在onReady函數(shù)中調(diào)起鍵盤,因為onReady函數(shù)是在頁面初次渲染完成時被調(diào)用。但是在實踐中我們發(fā)現(xiàn),對于一些配置不好的手機,其加載頁面速度較慢,在onReady函數(shù)調(diào)用時頁面并沒有渲染完畢,就會導致placeholder和input組件位置錯亂的現(xiàn)象。其本質(zhì)原因是,onReady生命周期函數(shù)并不能在調(diào)用時承若已經(jīng)將頁面渲染完成了。(盡管文檔中描述是已經(jīng)完成了。)
之前的操作是在onReady生命周期函數(shù)中調(diào)起鍵盤。
this.setData({ focus: true }) 復制代碼
發(fā)現(xiàn)這個問題后做了相應(yīng)的延遲處理
setTimeout(() => { this.setData({ focus: true }) }, 300) 復制代碼
但這是治標不治本的方法,手機性能好的用戶會無謂的等待300毫秒,而手機性能很差的用戶等待300毫秒也不一定就能解決這個問題。
解決思路
那么既然小程序并沒有提供給我們一個理想的渲染結(jié)束后的回調(diào)函數(shù),那么我們就換個思路: 使用短輪詢來處理,當頁面渲染完成后才調(diào)起鍵盤的操作。
既然要使用短輪詢,那么我們?nèi)ポ喸兪裁茨??什么標志代表著頁面渲染完成了呢?在這里,我是使用 wx.createSelectorQuery() 方法,它會返回一個SelectorQuery對象實例,在這個實例上調(diào)用select方法選擇我想要去輪詢的節(jié)點,在回調(diào)函數(shù)中判斷參數(shù)是否為 null 。如果返回了監(jiān)控的節(jié)點信息,那么說明已經(jīng)渲染完成。這時就可以進行鍵盤調(diào)起操作了。
let timer = setInterval(() => { wx.createSelectorQuery().select('#comment-section').boundingClientRect(rect => { if (rect !== null && timer !== null) { clearInterval(timer) timer = null this.setData({ focus: true }) } }).exec() }, 50) 復制代碼
在此之上,如果我們只粗暴的讓 focus 為 true 并不是個明智的做法。
在調(diào)起鍵盤時默認頁面會上推,如果在評論很少的情況下這樣的體驗并不好。所以需要判斷一個高度,超過這個值就上推,沒超過就不上推。這個值視實際情況而定。 上推的操作是由input組件的 adjust-position 屬性決定,為true則上推,否則則不上推。這時回調(diào)返回的參數(shù)中的節(jié)點信息就可以派上用場了。
// 在this.setData({ focus: true })前對節(jié)點高度進行判斷 if (rect.height < 500) this.setData({ push: false }) else this.setData({ push: true }) 復制代碼
onBlur函數(shù)問題
在實際的操作中,我們發(fā)現(xiàn)在鍵盤被調(diào)起后會有概又自動收回。經(jīng)過排查發(fā)現(xiàn)時onBlur函數(shù)的問題,在onBlur函數(shù)中,我們手動的設(shè)置 focus 為 false ,但其實并不需要這一步操作,反而帶來了副作用。在我們?nèi)コ诉@部分代碼后,鍵盤自動收起的問題得到了解決。
封裝起來
雖然我們完成了這次任務(wù)的需求,但是顯而易見的,這樣的任務(wù)在未來肯定還會再次出現(xiàn)。所以機智的我們應(yīng)該趕快把整套流程封裝起來,以便下次直接調(diào)用。
那么這時我們使用的方式就是這樣的:
const Util = require("xxx") // 引入封裝的庫 /** * 生命周期函數(shù)--監(jiān)聽頁面初次渲染完成 */ onReady: function () { Util.onTotalReady('#comment-section', 50, rect => { if (rect.bottom < 500) this.setData({ push: false }) else this.setData({ push: true }} this.setData({ focus: true }) }) } 復制代碼
在解決鍵盤調(diào)起的這個過程中我們可以看出微信小程序開發(fā)流程的簡陋,這個問題的出現(xiàn)本質(zhì)上是小程序提供給我們的生命周期函數(shù)的不夠準確。否則在頁面渲染完成的情況下我怎么會拿不到節(jié)點信息呢?像react中的componentWillMount生命周期函數(shù)中就不會出現(xiàn)這樣的問題,所以希望小程序能再變強大一些,也讓我們少寫一點這種hack代碼。
HiShop小程序工具提供多類型商城/門店小程序制作,可視化編輯 1秒生成5步上線。通過拖拽、拼接模塊布局小程序商城頁面,所看即所得,只需要美工就能做出精美商城。更多小程序商店請查看:小程序商店