NewsNing
NewsNing
  • 发布:2018-01-18 11:25
  • 更新:2018-01-18 11:25
  • 阅读:4192

【5+】Webview页面之间的数据交流

分类:HTML5+

一个App,其中大部分是要对页面之间的数据进行交互。

123

碧如:A打开B页面,B页面执行一些代码,再通知回A页面。

这可能是h5+er们遇到最常见的一个场景了。

ok,我们将问题实例化:

A页面有个选择地区的按钮,需要打开B页面选择一个地区,然后获取到选取结果返回给A页面并展示。

我们看看用mui.fire怎么来实现这个功能

123

A页面

1

        <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页面

2

        <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。

3

但是!我个人还是建议脱离mui.js来实现这个功能

4

可以借用咱们之前文章里面的讲过的,利用webview对象的evalJS方法

【5+】跨webview多页面 触发事件(一)
【5+】跨webview多页面 触发事件(一)

感觉用Broadcast.js有点小题大做

5

那咱们就写一个类似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('天行健, 君子以自强不息. ')  
    }  
}
4 关注 分享
Trust lhyh BoredApe 赵梦欢

要回复文章请先登录注册

NewsNing

NewsNing (作者)

回复 赵梦欢 :
哈哈,配合Rx.js用起来很爽的
2018-01-19 11:56
赵梦欢

赵梦欢

不错的想法
2018-01-18 22:17
NewsNing

NewsNing (作者)

回复 lhyh :
多谢大佬捧场
2018-01-18 13:32
NewsNing

NewsNing (作者)

回复 小资电脑 :
大概就是mui.fire的原理以及脱离mui.js的情况啦
2018-01-18 13:32
lhyh

lhyh

宁大出品,必属精品
2018-01-18 12:32
小资电脑

小资电脑

没细看 :) 这么多内容 是不是太复杂了? 我直接用mui.fire搞定
2018-01-18 12:03