Vue2实现关闭新打开的填报页面,刷新旧页面表格数据

Vue2实现关闭新打开的填报页面,刷新旧页面表格数据

方法一: 使用window对象的opener属性

window.opener:返回打开当前窗口的那个窗口的引用,例如:在 window A 中打开了 window B,B.opener 返回 A.

案例:旧页面是填报表格(包含状态:比如待填报、已填报),点击“填报”按钮后,跳转到新页面进行信息填报。填报完成,点击新页面的“填报完成”按钮后,刷新旧页面的表格请求(刷新后,新请求回的表格数据的状态变为“已填报”),关闭新页面。

以下为vue示例:

旧页面:

// mounted时,给window对象赋值属性reflashTable
mounted() {
  window.reflashTable = this.reflashTable
},
methods: {
    reflashTable() {
       // 请求表格数据方法
    },
    add() {
       // 填报,打开新页面
       const href = '...'
       window.open(href, '_blank')
    }
}

新页面:

methods: {
   async submit() {
        // 新页面,提交信息成功后
        const res = await ...
        if (res.code === 200) {
           // 刷新父页面数据
           if (window.opener) {
             window.opener.reflashTable()
           }
           // 关闭新页面
           window.close()
        }
       
    }
}

注意:方法一如果新打开的页面和旧页面存在跨域,例如新页面和旧页面的域名不同时,js代码window.opener.reflashTable是不执行的,解决跨域问题,见方法三window的postMessage方法实现跨源通信。

参考文献:

window.opener - Web API | MDN (mozilla.org)

方法二:使用document的visibilitychange事件

Document:visibilitychange 事件:当其选项卡的内容变得可见或被隐藏时,会在 document 上触发 visibilitychange 事件。注意:该事件不可取消。

同样,给出对应方法二的示例,vue示例如下:

旧页面:

// mounted时,监听visibilitychange事件
mounted() {
    // 监听当前tab是否可见,可见性变化事件,用于跳转到新页面时,返回自动刷新页面
    // 注意:visibilitychange事件不能清除
    document.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'visible') {
        // console.log('visible')
        // 可见时,重新查询。
        // 请求表格数据方法
        this.reflashTable()
      } else {
        // console.log('hidden')
      }
    })
},
methods: {
    reflashTable() {
       // 请求表格数据方法
    },
    add() {
       // 填报,打开新页面
       const href = '...'
       window.open(href, '_blank')
    }
}

新页面:

methods: {
   async submit() {
        // 新页面,提交信息成功后
        const res = await ...
        if (res.code === 200) {
           // 直接关闭新页面就行
           window.close()
        }
       
    }
}

方法二与方法一的区别:方法二是由旧页面监听visibilitychange事件来自行控制自己,只要重新切换回旧页面的选项卡时,就会重新请求表格数据;而方法一是新页面通过window的opener属性,拿到旧页面的window对象,由新页面控制触发旧页面的重新请求。

参考文献:

Document:visibilitychange 事件 - Web API | MDN (mozilla.org)

方法三: 使用window对象的postMessage方法和message事件

window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为 https),端口号(443 为 https 的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。强烈建议阅读一下mdn对该部分的描述

同样,给出对应方法三的示例,vue示例如下(注意:以下代码未真实试验过,请辨别使用):

旧页面:

// mounted时,旧页面监听message事件
mounted() {
  window.addEventListener("message", this.receiveMessage, false);
},
methods: {
    receiveMessage(event) {
      // For Chrome, the origin property is in the event.originalEvent
      var origin = event.origin || event.originalEvent.origin;
      // 为了安全,使用 origin 属性验证发件人的身份
      if (origin !== "http://example.org:8080") return; // "http://example.org:8080"改为新页面的对应的。注意:部署后,域名等的改变,配置为部署后的
      // if (origin !== window.location.origin) return; // 不跨域时,直接判断
      // 请求表格数据方法
      this.reflashTable(event)
    },
    reflashTable(event) {
       // 请求表格数据方法
    },
    add() {
       // 填报,打开新页面
       const href = '...'
       window.open(href, '_blank')
    }
}

新页面:

methods: {
   async submit() {
        // 新页面,提交信息成功后
        const res = await ...
        if (res.code === 200) {
           // 向父页面通信
           if (window.opener) {
             const targetOrigin = window.opener.location.origin
             window.opener.postMessage("message", targetOrigin)
           }
           // 关闭新页面
           window.close()
        }
       
    }
}

方法三与方法一:方法三解决了方法一不能跨源通信的问题。

参考文献:

window.postMessage - Web API | MDN (mozilla.org)

总结

在真实项目应用上

  1. 若新页面和旧页面不存在跨域问题,直接使用方法一或方法二(方法三也行,相对方法一和方法二复杂些)。方法一相对简单点,但存在跨源通信问题。方法二的visibilitychange事件不能取消且只要重新切换回旧页面该tab,就会触发事件。

  2. 若新页面和旧页面存在跨域问题,使用方法三。但旧页面为了安全(使用 origin 属性验证发件人的身份),判断时,需改为部署后新页面的origin。

如果文章存在什么问题,或者还有其他实现思路,欢迎在评论区讨论

  • 25
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值