商城系統(tǒng) 注冊(cè)

微信小程序調(diào)起鍵盤(pán)性能優(yōu)化

2018-07-25|HiShop
導(dǎo)讀:在 小程序 中,我們經(jīng)常有調(diào)起鍵盤(pán)的操作場(chǎng)景,但是在不同的場(chǎng)景下解決方案不盡相同,還是需要具體問(wèn)題具體分析。 需求分析 最近在項(xiàng)目中有一個(gè)需求,是從列表頁(yè)點(diǎn)擊評(píng)論按鈕進(jìn)...

在小程序中,我們經(jīng)常有調(diào)起鍵盤(pán)的操作場(chǎng)景,但是在不同的場(chǎng)景下解決方案不盡相同,還是需要具體問(wèn)題具體分析。

微信小程序調(diào)起鍵盤(pán)性能優(yōu)化

需求分析

最近在項(xiàng)目中有一個(gè)需求,是從列表頁(yè)點(diǎn)擊評(píng)論按鈕進(jìn)入詳情頁(yè)時(shí),在加載完頁(yè)面后自動(dòng)調(diào)起鍵盤(pán)進(jìn)入評(píng)論狀態(tài)。從需求來(lái)看,我們應(yīng)該在onReady函數(shù)中調(diào)起鍵盤(pán),因?yàn)閛nReady函數(shù)是在頁(yè)面初次渲染完成時(shí)被調(diào)用。但是在實(shí)踐中我們發(fā)現(xiàn),對(duì)于一些配置不好的手機(jī),其加載頁(yè)面速度較慢,在onReady函數(shù)調(diào)用時(shí)頁(yè)面并沒(méi)有渲染完畢,就會(huì)導(dǎo)致placeholder和input組件位置錯(cuò)亂的現(xiàn)象。其本質(zhì)原因是,onReady生命周期函數(shù)并不能在調(diào)用時(shí)承若已經(jīng)將頁(yè)面渲染完成了。(盡管文檔中描述是已經(jīng)完成了。)

之前的操作是在onReady生命周期函數(shù)中調(diào)起鍵盤(pán)。

this.setData({ focus: true })
復(fù)制代碼

發(fā)現(xiàn)這個(gè)問(wèn)題后做了相應(yīng)的延遲處理

setTimeout(() => {
  this.setData({ focus: true })
}, 300)
復(fù)制代碼

但這是治標(biāo)不治本的方法,手機(jī)性能好的用戶會(huì)無(wú)謂的等待300毫秒,而手機(jī)性能很差的用戶等待300毫秒也不一定就能解決這個(gè)問(wèn)題。

解決思路

那么既然小程序并沒(méi)有提供給我們一個(gè)理想的渲染結(jié)束后的回調(diào)函數(shù),那么我們就換個(gè)思路: 使用短輪詢來(lái)處理,當(dāng)頁(yè)面渲染完成后才調(diào)起鍵盤(pán)的操作。

既然要使用短輪詢,那么我們?nèi)ポ喸兪裁茨??什么?biāo)志代表著頁(yè)面渲染完成了呢?在這里,我是使用 wx.createSelectorQuery() 方法,它會(huì)返回一個(gè)SelectorQuery對(duì)象實(shí)例,在這個(gè)實(shí)例上調(diào)用select方法選擇我想要去輪詢的節(jié)點(diǎn),在回調(diào)函數(shù)中判斷參數(shù)是否為 null 。如果返回了監(jiān)控的節(jié)點(diǎn)信息,那么說(shuō)明已經(jīng)渲染完成。這時(shí)就可以進(jìn)行鍵盤(pán)調(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)
復(fù)制代碼

在此之上,如果我們只粗暴的讓 focus 為 true 并不是個(gè)明智的做法。

在調(diào)起鍵盤(pán)時(shí)默認(rèn)頁(yè)面會(huì)上推,如果在評(píng)論很少的情況下這樣的體驗(yàn)并不好。所以需要判斷一個(gè)高度,超過(guò)這個(gè)值就上推,沒(méi)超過(guò)就不上推。這個(gè)值視實(shí)際情況而定。 上推的操作是由input組件的 adjust-position 屬性決定,為true則上推,否則則不上推。這時(shí)回調(diào)返回的參數(shù)中的節(jié)點(diǎn)信息就可以派上用場(chǎng)了。

// 在this.setData({ focus: true })前對(duì)節(jié)點(diǎn)高度進(jìn)行判斷
if (rect.height < 500) this.setData({ push: false })
else this.setData({ push: true })
復(fù)制代碼

onBlur函數(shù)問(wèn)題

在實(shí)際的操作中,我們發(fā)現(xiàn)在鍵盤(pán)被調(diào)起后會(huì)有概又自動(dòng)收回。經(jīng)過(guò)排查發(fā)現(xiàn)時(shí)onBlur函數(shù)的問(wèn)題,在onBlur函數(shù)中,我們手動(dòng)的設(shè)置 focus 為 false ,但其實(shí)并不需要這一步操作,反而帶來(lái)了副作用。在我們?nèi)コ诉@部分代碼后,鍵盤(pán)自動(dòng)收起的問(wèn)題得到了解決。

封裝起來(lái)

雖然我們完成了這次任務(wù)的需求,但是顯而易見(jiàn)的,這樣的任務(wù)在未來(lái)肯定還會(huì)再次出現(xiàn)。所以機(jī)智的我們應(yīng)該趕快把整套流程封裝起來(lái),以便下次直接調(diào)用。

 

那么這時(shí)我們使用的方式就是這樣的:

const Util = require("xxx") // 引入封裝的庫(kù)

/**
 * 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面初次渲染完成
 */
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 })
  })
}
復(fù)制代碼

在解決鍵盤(pán)調(diào)起的這個(gè)過(guò)程中我們可以看出微信小程序開(kāi)發(fā)流程的簡(jiǎn)陋,這個(gè)問(wèn)題的出現(xiàn)本質(zhì)上是小程序提供給我們的生命周期函數(shù)的不夠準(zhǔn)確。否則在頁(yè)面渲染完成的情況下我怎么會(huì)拿不到節(jié)點(diǎn)信息呢?像react中的componentWillMount生命周期函數(shù)中就不會(huì)出現(xiàn)這樣的問(wèn)題,所以希望小程序能再變強(qiáng)大一些,也讓我們少寫(xiě)一點(diǎn)這種hack代碼。

HiShop小程序工具提供多類(lèi)型商城/門(mén)店小程序制作,可視化編輯 1秒生成5步上線。通過(guò)拖拽、拼接模塊布局小程序商城頁(yè)面,所看即所得,只需要美工就能做出精美商城。更多小程序商店請(qǐng)查看:小程序商店

電話咨詢 預(yù)約演示 0元開(kāi)店