1. 程式人生 > >H5頁面監聽Android物理返回鍵

H5頁面監聽Android物理返回鍵

Android物理返回鍵的點選事件,一般webview的預設行為是 window.history.go(-1) ,但是在實際需求場景下,簡單的頁面回退並不能滿足需求,所以需要H5頁面監聽Android物理返回鍵從而自定義處理方法。

本方案的程式碼都在 h5_android_back 倉庫中

原理

主要是運用 HTML5 History API 實現。所以,首先簡單介紹下 HTML5 History API

HTML5 History API

history 屬性

history.length

history.state
複製程式碼

history 方法

history.back()

history.forward()

history.go()
複製程式碼

HTML5 新API

history.pushState(state, title, url); 新增一條歷史記錄,不重新整理頁面
history.replaceState(state, title, url); 替換一條歷史記錄,不重新整理頁面

事件

popState事件:歷史記錄發生變化時觸發,呼叫history.pushState()history.replaceState()不會觸發此事件
window.addEventListener('popstate', handlePopstate);
複製程式碼
hashchange事件:頁面hash值發生改變時觸發
window
.addEventListener('hashchange', handleHashChange); 複製程式碼

監聽Android物理返回鍵實現

// index.js
(function (pkg) {
    var STATE = '_android_back';
    // 維護處理方法的棧
    var _android_back_handles = [];
    // 觸發一次popstate方法,則呼叫最新處理方法
    var handlePopstate = function () {
        var handle = _android_back_handles.pop();
        handle && handle();
    };
    // 通過呼叫listen方法新增處理方法
var listen = function (handle) { _android_back_handles.push(handle); }; // 通過呼叫push方法,新增一條歷史記錄,並新增對應處理方法 var push = function (state, handle) { if (handle) { history.pushState(state, null, location.href); handle && _android_back_handles.push(handle); } }; const init = function () { // 通過呼叫 history.pushState() 方法新增一條歷史記錄 history.pushState(STATE, null, location.href); // 監聽 popstate 事件,當點選Android物理返回鍵時,會觸發該事件 window.addEventListener('popstate', handlePopstate); this.listen = listen; this.push = push; }; init.call(window[pkg] = window[pkg] || {}); })('AndroidBack'); 複製程式碼

此實現參考了 github.com/iazrael/xba… ,在此基礎上,根據需要修改和添加了一部分程式碼

此外,封裝了一個React高階元件,方便React專案使用,程式碼如下:

import * as React from 'react';

export default (Target, handleBack) => {
    return class AndroidBack extends React.Component {
        _handles = []
        back = () => {
            window.history.go(-1);
        }
        componentDidMount () {
            // 通過呼叫 history.pushState() 方法新增一條歷史記錄
            history.pushState('_android_back', null, location.href);
            // 監聽 popstate 事件,當點選Android物理返回鍵時,會觸發該事件
            window.addEventListener('popstate', this.handlePopstate);
            if (handleBack) {
                // 新增自定義處理方法
                this._handles.push(handleBack);
            } else {
                // 如果沒有自定義處理方法,預設呼叫 window.history.go(-1);
                this._handles.push(this.back);
            }
        }
        componentWillUnmount () {
            window.removeEventListener('popstate', this.handlePopstate);
        }
        // 觸發一次popstate方法,則呼叫最新處理方法
        handlePopstate = () => {
            const handle = this._handles.pop();
            handle && handle();
        }
        // 通過呼叫push方法,新增一條歷史記錄,並新增對應處理方法
        push = (state, handle) => {
            if (handle) {
                history.pushState(state, null, location.href);
                this._handles.push(handle);
            }
        }
        render () {
            return (
                <Target {...this.props} _android_back_push={this.push}/>
            );
        }
    };
};
複製程式碼

實現原理基本在註釋中註明,在這就不詳細敘述了,所有程式碼在 h5_android_back 倉庫中

使用

兩種方式:

1、將物件掛在window上,支援任意頁面接入,使用如下:

index.js

// 監聽Android物理返回鍵,自定義處理方法
window.AndroidBack.listen(() => {
    console.log('back');
});
// 新增Android物理返回鍵監聽事件,使用場景,比如:頁面內彈出浮層,點選Android物理返回鍵,不是回退頁面,而是關閉浮層
window.AndroidBack.push('close_modal', () => {
    // 關閉彈窗
    console.log('close_modal');
});
複製程式碼

2、封裝了React高階元件,支援React專案接入,使用如下:

index_react.js

import * as React from 'react';
import AndroidBack from 'h5_android_back/index_react.js';

class App extends React.Component {
    // ...
    openModal = () => {
        // 新增Android物理返回鍵監聽事件,使用場景,比如:頁面內彈出浮層,點選Android物理返回鍵,不是回退頁面,而是關閉浮層
        this.props._android_back_push('close_modal', () => {
            // 關閉彈窗
            console.log('close_modal');
        });
    }
}

// 監聽Android物理返回鍵,自定義處理方法
export default AndroidBack(App, () => {
    console.log('back');
})
複製程式碼

寫在最後

注:此方案使用於所有瀏覽器及預設行為是頁面回退的webview

此方案在我平時工作中使用正常,希望能對有需要的小夥伴有幫助~~~

喜歡我的文章小夥伴可以去 我的個人部落格 點star ⭐️