微前端——Vue页面集成(iframe篇)

208 阅读2分钟

微前端——Vue页面集成(iframe篇)

背景:最近公司有个需求,需要页面集成。这里我选的是iframe来实现,记录一下。

需求:有两个已经完成的项目,分别叫做A项目,B项目,现在需要将B项目的所有页面集成到A项目。

问题:由于两个都是独立的项目,并且都有自己的单独的登录入口。所以将B项目集成到A项目需要实现免登录。

解决方案:这里用到iframe来实现

实现免登录

1、在A项目中新建src/views/Integration/index.vue文件

<template>
	   <!-- 渲染B项目页面 :src这里的地址是B项目的页面地址 -->
     <iframe id="iframe" :src="`http:127.0.0.1:8080/${url}`" frameborder="0" class="mainIframe"></iframe>
</template>

<script>
export default {
    data(){
        return {
            iframe:null,
            //B项目路由地址
            routeList:[
                {path:'/home',title:'首页'},
                {path:'/about',title:'关于'}
            ]
        }
    },
    //当A项目切换菜单时,匹配B项目的路由地址
    computed:{
        url(){
            return this.routeList.find(item=>{return item.title===this.$route.meta.title})      
        }
    },
    mounted(){
        this.initData()
    },
    methods:{
        initData(){
            this.iframe = document.getElementById('iframe')
            this.iframe.onload = function(){
                //A项目向B项目传值,第一个参数是传的值,第二个参数是目标源(A项目的地址)
                that.iframe.contentWindow.postMessage('username','http:127.0.0.1:8080')
            }
        }
    }
    
}
</script>
<style scoped>
.mainIframe{
    width: 100%;
    height: calc(100vh - 80px);
    margin:20px;
   
}
</style>

2、在A项目中src/router/index.js 路径下配置对应路由菜单

import Vue from "vue";
import VueRouter from "vue-router";
import routes from "./routes";
Vue.use(VueRouter);
cosnt routes = [
 {
  name:"Home",
  path:"/home",
  meta:{title:'首页'}
  component:()=>import('@/Integration/index')
 },
 {
  name:"About",
  meta:{title:'关于'}
  path:"/about",
  component:()=>import('@/Integration/index')},
]
const router = new VueRouter({
    routes,
    mode:"history"
})
export default router;

3、在B项目login.vue页面中

<script>
export default{
    mounted(){
        this.exemptLogin()
    },
    methods:{
        exemptLogin(){
            let that = this
            window.addEventListener('message', function(e) {
            	if(e&&e.data && !e.data.type){
                    //免登录接口,拿到用户名生成token和用户信息返回
                    that.apiLogin({
                      username:e.data
                    }).then(res=>{
                      if(res.code==1000){
                          //这里将B项目原来登录入口,登录跳转之前获取数据的代码copy过来
                          that.$message.success('登录成功')
                      }                  
                    })
                }
            })            
        }
    }
}
</script>
最后总结:

1、A项目向B项目通信传值

//第二个参数可以是*表示不限制目标源,可以是任何源向iframe发送消息。当iframe加载不同域的内容时,此时需要跨域通信,我们可以用*
//但是为了防止跨站脚本攻击,我们可以指定目标源。
iframe.contentWindow.postMessage("A项目需要传的值","A项目的域名地址")

2、B项目向A项目通信传值

window.parent.postMessage("B项目需要传的值","B项目的域名地址");

3、两个项目接收值,都可以使用addEventListener来监听

  window.addEventListener('message', function(e) {
  	//打印e可以看到,传过来的值
  }