【5+】Webview頁面之間的數據交流

一個App,其中大部分是要對頁面之間的數據進行交互。
1DBFB83E6BDA9816D35E4796DE55BB0Bjavascript

碧如:A打開B頁面,B頁面執行一些代碼,再通知回A頁面。html

這多是h5+er們遇到最多見的一個場景了。java

ok,咱們將問題實例化:web

A頁面有個選擇地區的按鈕,須要打開B頁面選擇一個地區,而後獲取到選取結果返回給A頁面並展現。segmentfault

咱們看看用mui.fire怎麼來實現這個功能app

e9fbd9d5a31f5e16

A頁面函數

clipboard.png

<header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">A</h1>
        </header>
        <div class="mui-content">
            <input type="text" readonly placeholder="未選擇">
            <button type="button" class="mui-btn mui-btn-blue">選取地區</button>
        </div>
        
        <script src="js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init();
            // 自定義監聽select事件
            document.addEventListener('select', function(e){
                var text = e.detail.text;
                document.querySelector("input").value = text;
            });
            // 按鈕點擊事件
            document.querySelector(".mui-btn-blue").addEventListener('tap', function(){
                // 打開B頁面,選取一個結果
                mui.openWindow('B.html');
            });
        </script>

B頁面測試

clipboard.png

<header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title">B</h1>
        </header>
        <div class="mui-content">
            <ul class="mui-table-view">
                <li class="mui-table-view-cell">
                    <a class="mui-navigate-right">
                        上海
                    </a>
                </li>
                <li class="mui-table-view-cell">
                    <a class="mui-navigate-right">
                        深圳
                    </a>
                </li>
                <li class="mui-table-view-cell">
                    <a class="mui-navigate-right">
                        北京
                    </a>
                </li>
            </ul>
        </div>

        <script src="js/mui.min.js"></script>
        <script type="text/javascript">
            mui.init();
            mui('ul').on('tap', 'li', function() {
                // 獲取當前選擇的內容
                var text = this.innerText;
                // 通知上個頁面
                var w = plus.webview.currentWebview();
                var opener = w.opener();
                mui.fire(opener, "select",{
                    text: text
                });
                // 關閉本頁面
                w.close();
            });

真機調試一下,o98k。ui

clipboard.png

可是!我我的仍是建議脫離mui.js來實現這個功能this

clipboard.png

能夠借用我們以前文章裏面的講過的,利用webview對象的evalJS方法

【5+】跨webview多頁面 觸發事件(一)
【5+】跨webview多頁面 觸發事件(一)

感受用Broadcast.js有點小題大作

clipboard.png

那我們就寫一個相似Android中的onActivityResult和setResult方法

新建一個app.js,做爲一個本身的插件,裏面實現兩個方法 onActivityResult 和 setResult

(function(app){
    
    /**
     * 打開一個頁面
     * @param {String} url 頁面路徑
     * @param {String} id 頁面id
     * @param {Object} ex 參數
     * @param {Function} callback 
     */
    app.onActivityResult = function(url, id, ex, callback){
        
    };
    
    /**
     * 返回建立者頁面數據
     * @param {Object} data 須要返回的數據
     * @return {Webview} w 當前webview
     */
    app.setResult = function(data){
        
    };
    
    
}(window.app || (window.app = {})));

咱們一步步來,先看看setResult如何觸發上個頁面的函數

/**
     * 返回建立者頁面數據
     * @param {Object} data 須要返回的數據
     * @return {Webview} w 當前webview
     */
    app.setResult = function(data){
        // 獲取當前webview
        var indexW = plus.webview.currentWebview();
        // 獲取建立者的webview
        var opener = indexW.opener();
        // 執行js字符串
        opener.evalJS();// ??????
    };

臥槽,那麼,問題來了,evalJS該執行什麼呢?

若是我在A頁面的window對象下定一個函數

window.test = function(data){
    alert(JSON.stringify(data));
}

那麼,咱們在evalJS裏面就該這麼寫

// 執行js字符串
        var jsstr = "window.test && window.test(" + JSON.stringify(data) + ")";
        opener.evalJS(jsstr);

好吧,考慮到一個頁面可能經過這個方式打開多個頁面,那麼咱們這個test函數就得改一個不重複惟一的名稱,而且定義放到onActivityResult方法裏面

var _id = 0,
        _tempName = '',
        ow,cw;

        /**
         * 打開一個頁面
         * @param {String} url 頁面路徑
         * @param {String} id 頁面id
         * @param {Object} ex 參數
         * @param {Function} callback 
         */
        app.onActivityResult = function(url, id, ex, callback) {
            
            // 生成惟一回調函數名稱
            _tempName = 'APP_RESULT_FUN_' + _id++;
            // 定義函數
            window[_tempName] = function(data){
                // 執行自定義回調
                callback(data);
            };
            // 傳遞函數名稱到目標頁面
            ex.callbackName = _tempName;
            
            // 顯示菊花
            cw = plus.nativeUI.showWaiting();
            
            // 建立目標頁面 
            ow = plus.webview.create(url, id, {
                render: "always"
            }, ex);
            // title更新時顯示 頁面
            ow.addEventListener('titleUpdate', function(){
                // 關閉菊花
                cw && (cw.close(),cw = null);
                // 顯示頁面
                ow.show('pop-in');
            });
            // 頁面關閉時,註銷window下這次事件
            ow.addEventListener('close', function(){
                  setTimeout(function(){
                      window[_tempName] = null;
                  });
            });
            
        };

生成特殊一個函數,並把函數名經過extras的方式傳參到目標頁面,
相應的,setResult方法也須要少量更改

/**
     * 返回建立者頁面數據
     * @param {Object} data 須要返回的數據
     * @return {Webview} w 當前webview
     */
    app.setResult = function(data) {
        // 獲取當前webview
        var indexW = plus.webview.currentWebview();
        // js字符串
        var jsstr = "";
        // 若是存在自定義回調函數名
        if(indexW.callbackName){
            // 拼接js字符串
            jsstr = "window." + indexW.callbackName;
            jsstr = jsstr + "&&" + jsstr + "(" + JSON.stringify(data) + ")";
            // 執行
            indexW.opener().evalJS(jsstr);
        }
        // 返回當前頁面
        return indexW;
    };

試試引用後在AB頁面測試一下

// A頁面 按鈕點擊事件
            document.querySelector(".mui-btn-blue").addEventListener('tap', function(){
                // 打開B頁面,選取一個結果
                app.onActivityResult('B.html', 'B', {}, function(data){
                    // 修改內容
                    document.querySelector("input").value = data.text;
                });
            });
            
            // B頁面 選項點擊事件
            mui('ul').on('tap', 'li', function() {
                // 獲取當前選擇的內容
                var text = this.innerText;
                // 通知上個頁面 並關閉本頁面
                app.setResult({
                    text: text
                }).close();
            });

臥槽666。

class Man{
    constructor(){
        this.name = 'newsning'
    }
    say(){
        console.log('天行健, 君子以自強不息. ')
    }
}
相關文章
相關標籤/搜索