• 关于新开页面的传值问题


    欢迎大家访问我的博客dreamITGirl,不要吝啬你们的小星星,点个star~ 有问题的话,你可以将问题在 GitHub问我.

    新开浏览器页签的传值问题

    1. 业务背景

    在新建/修改/详情等二级或者三级新打开的页签中,需要实现传递参数的功能,并同时刷新上一级页面

    2. 思考方式:

    1. 使用 localStorage 的方式
      这种方式的最大的弊端是当项目较大的时候存储的信息量极易超过浏览器中要求的存储空间。所以我们在第一次迭代时放弃了这种方式。
    2. 使用window.postMessage
      这种方式在列表页面中打开一个新建页面时是没有问题的,但是当打开多个新建页面,这个传的值就会发生问题。导致信息接收失败。在调研这个方式后也放弃了这种思路
    3. 自封装插件
      思路:采用了JS打开页面的初始化事件,利用H5的新特性history来实现的。

    3. 代码解析

    主要是利用了history中的pushStatereplaceState这两个API,通过监听页面的渲染顺序,将函数设计成发布/订阅者模式,从而达到想要的效果

    function parseConfig (config) { // 将传递的参数String化
        let str = ''
        for (let key in config) {
            if (config[key] !== null) {
                str+=`${key}=${config[key]},`
            }
        }
        return str
    }
    
    const _historyWrap = function(type) { 
        const orig = history[type];
        const e = new Event(type);
        return function() {
            const rv = orig.apply(this, arguments);
            e.arguments = arguments;
            window.dispatchEvent(e); // 向一个指定的事件目标派发一个事件,  并以合适的顺序同步调用目标元素相关的事件处理函数
            return rv;
        }
    };
    
    history.pushState = _historyWrap('pushState');
    history.replaceState = _historyWrap('replaceState');
    
    class Win {
        constructor (url, config) {
            config = config || {}
            if (!url) {
                throw Error('url is not defined!')
            }
            let name = '_'+Date.now() // 确保name的唯一性
            this.win = window.open(url, name, parseConfig(config))
            window.addEventListener('beforeunload', ()=>{this.win.close()}) // 监听window,document 及其资源即将被载。
            window.addEventListener('pushState', ()=>{this.win.close()}); // history在会话历史堆栈顶部插入一条记录
            window.addEventListener('replaceState', ()=>{this.win.close()}); // history更新会话历史堆栈顶部记录信息
            window.addEventListener('popstate', ()=>{this.win.close()}); //history在会话历史堆栈顶部弹出一条记录
            if (this.win === null) {
                alert('请将“弹出式窗口和重定向”设置为允许')
                throw Error('新窗口创建失败,窗口被拦截!')
            }
            return this
        }
        on(eventName, cb) {
            if (eventName === 'load') {
                this.win.onload = (ev) => {
                    cb(ev, this)
                }
            }
            if (eventName === 'message') {
                let _this = this
                function closeListener() {
                    setTimeout(()=>{
                        _this.win.send = function(message){
                            cb(message)
                        }
                        _this.win.addEventListener('unload', closeListener)
                    })
                }
                this.win.addEventListener('unload', closeListener)
            }
        }
        close(cb) {
            cb && cb()
            window.name = 'Win_'+Date.now()
            this.win.open('',window.name)
            window.name = ''
            this.win.close()
        }
    }
    

    4. 知识点链接

  • 相关阅读:
    收集一些jQueryMobile的插件和案例[转]
    关于美工ps出图table格式的处理
    Sencha Touch 1.1.1 之初接触(一)怎样入手并写一个漂亮的demo[转]
    把Excel文件数据导入数据库,支持多工作表
    批量Excel数据导入Oracle数据库
    关于ASP.NET 中站点地图sitemap 的使用
    视频播放器
    asp.net SqlParameter关于Like的传参数无效问题(转载)
    分页
    告别ASP.NET操作EXCEL的烦恼
  • 原文地址:https://www.cnblogs.com/bllx/p/15927912.html
Copyright © 2020-2023  润新知