Vue实现跨项目间的数据访问🙂

5,570

心态决定成败,愿你以一个好的心态面对未来的生活😁

前言

需求场景如下:在Vue项目中,调用的接口,需要用户登录后通过token进行访问,此时登录的相关页面部署在同域名的不同路径里,无法在当前项目访问到,我们要如何拿到这个登陆页面返回的token?接下来就跟大家分享一种解决方案,先看下最终实现的效果🤒

实现思路

  • 页面创建完成后从本地存储中获取token
  • 判断token是否存在
  • 如果token不存在,则使用js弹出一个新的窗口打开登录页,如果token存在,则更新vuex中的token
  • 在登陆页面中:登录成功获取token,将token存到本地存储中,关闭当前打开的窗口
  • 监听到子窗口关闭,刷新当前窗口,更新vuex中的token
  • 核心:将需要的数据存到本地存储中,Vue从本地存储中读取数据

实现过程

下面代码中有用到lodash库进行非空校验,需要使用yarn | npm安装这个库,接口调用进行了API抽离,本文不做讲解,关于API抽离的实现,可以参考我的另一篇文章 Vue合理配置axios并在项目中进行实际应用

    // App.Vue
    created: function(){
      // 页面创建完成后,从localstorage中获取token更新vuex
      const token = localStorage.getItem("token");
      if(lodash.isEmpty(token)){
        // 跳转登录页
        let windowOBJ = this.openWin("https://www.kaisir.cn/login","loginWindow",800,675);
        // 使用定时器判断当前窗口是否关闭
        let loop = setInterval(()=>{
          if(windowOBJ.closed){
            clearInterval(loop);
            // 刷新当前页
            parent.location.reload();
          }
        },1);
      }else{
        // 更新vuex中的token
        this.$store.state.token = token;
      }
    },
    // 方法
    methods:{
      // 居中打开一个新窗口
      openWin:(url,name,iWidth,iHeight)=>{
        //获得窗口的垂直位置
        const iTop = (window.screen.availHeight - 30 - iHeight) / 2;
        // //获得窗口的水平位置
        const iLeft = (window.screen.availWidth - 10 - iWidth) / 2;
        return window.open(url, name, `width=${iWidth},height=${iHeight},top=${iTop},left=${iLeft},toolbar:0`);
      }
      
   // 测试需要验证接口的调用
   sendMessage:function(){
       this.$api.websiteManageAPI.getJSON(1,3).then((res)=>{
           console.log("接口调用成功");
           console.log(res)
       });
   }
   

踩坑记录

  • 子窗口关闭,刷新父页面

    刚开始的想法是在子窗口中刷新父页面,然后关闭当前子窗口。结果浏览器报错:未捕获的DOMException:阻止了起源为“ www.kaisir.cn”的框架访问跨域框架。然后就使用定时器监听子窗口关闭,在父窗口实现刷新。当然你不考虑跨域问题的话,可以在登录页面实现父窗口的刷新

      // 登录成功将token存储到本地存储,并刷新父页面
      localStorage.setItem("token",res.token);
      opener.location.reload();
      window.close();
    

  • 正确的实现方式:使用定时器轮巡,监听子窗口的关闭,然后刷新当前页面,清理定时器
   // 跳转登录页
   let windowOBJ =     this.openWin("https://www.kaisir.cn/login","loginWindow",800,675);
   // 使用定时器判断当前窗口是否关闭
    let loop = setInterval(()=>{
      if(windowOBJ.closed){
        clearInterval(loop);
        // 刷新当前页
        parent.location.reload();
      }
    },1);

写在最后

  • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
  • 本文首发于掘金,如需转载请评论区留言💌