小程序Ticker倒計時最佳實踐

Hello 小夥伴們,若是以爲本文還不錯,記得給個 star , 小夥伴們的 star 是我持續更新的動力!GitHub 地址git

一. 什麼是ticker?

tick原本的意思是鐘錶的滴答聲。Ticker類爲遊戲開發提供了一個主要的定時類。它主要的目的就是把stage渲染的工做集中起來,也就是說定時調用stage.update()這個方法。Ticker設置的頻率也就是遊戲的幀數了。 咱們把Ticker應用到小程序開發中,頻率設置爲1s。github

Ticker的使用以下,初始化Ticker對象,添加偵聽tick事件,啓動ticker。小程序

const ticker = new Ticker()
// 參數爲Object類型,必須有tick方法
ticker.addTick({
    tick: (delta) => {
    	...
    }
})
ticker.start()
複製代碼

這裏不細說Ticker的實現,詳情請看Ticker.js源碼。bash

二. 小程序倒計時的煩惱

假如咱們都在頁面onShow設置setTimeout。 一、onHide取消clearTimeout。假如首頁有個倒計時在倒數100S,進入二級頁面後,觸發onHide,取消clearTimeout。過了10S返回首頁,又從新啓動setTimeout,那麼應該是從100S仍是90S開始倒數呢? 那確定是90S開始呀,但是setTimeout都停了,怎麼記錄到過去了10S呢? 二、onUnload 取消clearTimeout。onHide以後,其實倒計時還在後臺執行,setData也在從新渲染。若是有多級頁面,無疑是很是浪費性能。app

三. Ticker實現countdown解決方案

在Page的生命週期函數中,添加tick處理。ide

import ticker from './utils/ticker'

Page({
	countdown: 100,
	// 添加當前頁面對象到ticker隊列
	onLoad () {
		ticker.addTick(this)
	},
	// 恢復當前頁面對象tick
	onShow () {
		ticker.resume(this)
	},
	// 暫停當前頁面對象tick
	onHide () {
		ticker.pause(this)
	},
	// 移除當前頁面對象tick從ticker隊列
	onUnload () {
		ticker.removeTick(this)
	},
	// 須要計時的頁面添加tick方法
	tick (delta) {
		countdown -= delta
		this.setData({
			countdown
		})
	}
})
複製代碼

統一處理Page的tick

每一個須要用ticker的頁面,都須要在各自的生命週期函數裏面添加對應的操做。重複的工做交給代碼,來重寫Page構造函數。interceptor.js函數

// 生命週期函數集合
const Interceptor = {
    onLoad: [], onShow: [], onHide: [], onUnload: []
}

/**
 * 組合函數,依次執行
 * @param  {...Function} args 被組合的函數
 */
function compose(interceptorList, sourceMethod){
    return function () {
        [...interceptorList, sourceMethod].forEach( fn => {
            typeof fn === 'function' && fn.call(this, arguments)
        });
    }
}

/**
 * 小程序Page方法的替代實現
 */
const wxPage = Page

/**
 * 重寫Page構造函數
 * @param pageObject - 傳入的頁面對象
 */
Page = function (pageObject) {
    Object.keys(Interceptor).forEach((keyName) => {
        const sourceMethod = pageObject[keyName]
        pageObject[keyName] = compose(Interceptor[keyName], sourceMethod)
    })
    return wxPage(pageObject)
}

/**
 * 增長對Page生命週期方法的攔截器
 * @param methodName
 * @param handler
 */
export function addInterceptor (methodName, handler) {
    Interceptor[methodName] && Interceptor[methodName].push(handler)
}
複製代碼

小程序入口文件app.js,給頁面生命週期函數全局注入ticker對應的方法。性能

import * as Interceptor from './utils/interceptor'
import ticker from './utils/ticker'

Interceptor.addInterceptor('onLoad', function () {
    ticker.addTick(this)
})

Interceptor.addInterceptor('onShow', function () {
    ticker.resume(this)
})

Interceptor.addInterceptor('onHide', function () {
    ticker.pause(this)
})

Interceptor.addInterceptor('onUnload', function () {
    ticker.removeTick(this)
})

App({
    onLaunch () {
        
    }
})
複製代碼

頁面只須要添加tick方法,利用delta計算倒數時間,無需操做ticker邏輯。page.js:ui

import formatTime from '../../utils/formatTime'
Page({
    countdown: 1000,
    data: {
        countdownStr: ''
    },
    tick (delta) {
        console.log('index tick')
        let countdownStr = formatTime(this.countdown -= delta)
        this.setData({
            countdownStr
        })
    }
});
複製代碼

donethis

Github: github.com/songdy/todo…

相關文章
相關標籤/搜索