欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue集成Iframe页面的方法示例

程序员文章站 2022-04-14 13:00:40
1. 项目需求 我们切换为vue框架是后面的事情,之前还有一些功能页面是用jsp页面写的,而我们的管理系统需要既支持vue的url,又要支持这些发布之后的jsp页面...

1. 项目需求

我们切换为vue框架是后面的事情,之前还有一些功能页面是用jsp页面写的,而我们的管理系统需要既支持vue的url,又要支持这些发布之后的jsp页面

还有一个就是切换tab回来的时候之前输入的东西还要存在

系统页面截图

Vue集成Iframe页面的方法示例

2. 实现思路

针对这个问题,我们最开始的实现思路是写了一个iframe的通用组件,然后把不同的http的页面的url传递进来进行切换,但是这样不满足第二条,我们发现只要切换了vue的路由,然后再切回http的页面,iframe中的src属性的页面就会从新刷新,没有办法保留住东西,于是就有了下面的实现思路

我们在vue的router-view同级别添加了一个iframetemp组件,其实就是一个elementui的tab组件,然后把tab组件的头的样式隐藏在我们菜单栏的下面

<template>
 <!--路由渲染的功能模块区域-->
 <div class="router-out-content">
  <!--缓存部分页面的写法-->
  <keep-alive>
   <router-view v-show="!showiframe" class="position router-content" v-if="$route.meta.keepalive"></router-view>
  </keep-alive>
  <router-view v-show="!showiframe" class="position router-content" v-if="!$route.meta.keepalive"></router-view>
  <!--兼容系统外部页面-->
  <iframe-temp v-show="showiframe"></iframe-temp>
 </div>
</template>
<style scoped lang="scss">
 .position {
  position: relative
 }

 .router-out-content {
  position: static;
 }
</style>
<script>
import { mapstate } from 'vuex'
import iframetemp from '@/containers/main/iframetemplate.vue'
export default {
 data() {
  return {}
 },
 components: {
  iframetemp
 },
 computed: {
  ...mapstate([
   'showiframe'
  ])
 }
}
</script>

/*
 * iframetemplate.vue组件的内部
 **/

 <template>
 <!--iframe页面展示区域-->
 <div id="fwiframe">
  <!--<tabs class="full temporary-tabs" v-model="store.state.iframeselecttab" type="card">-->
  <tabs class="full temporary-tabs" :value="iframeselecttab" type="card">
   <tabpane
    v-for="(item, index) in iframetabdata"
    :key="item.tag"
    :label="item.name"
    :name="item.tag"
   >
    <iframe :key="item.tag" v-once :src="item.url" frameborder="0"></iframe>
   </tabpane>
  </tabs>
 </div>
</template>
<style lang="scss">
 #fwiframe {
  /*测试位置的时候显示这段--开始*/
  /*width: 100%;*/
  /*height: 100%;*/
  /*background-color: red;*/
  /*display: block !important;*/
  /*测试位置的时候显示这段--结束*/
  position: absolute;
  left: 0;
  right: 0;
  top: 45px;
  bottom: 0;
  z-index: 5000 !important;
  .el-tab-pane {
   height: 100%;
   width: 100%;
   iframe {
    /*height: auto;*/
    min-height: 600px;
    /*height: calc(100% - 45px);*/
    width: 100%;
   }

  }
  .full {
   position: relative;
   left: 0;
   right: 0;
   top: 0;
   bottom: 0;
  }
 }
</style>
<script>

 // selecttabcode=>iframeselecttab
 // tabslist=>iframetabdata
 import {mapstate} from 'vuex'
 import * as mainconst from '@/store/mainconst.js'
 export default{
  data(){
   return {
//    tabslist: [],
//    selecttabcode: ''
   }
  },
  computed: {
   ...mapstate([
    'iframetabdata',
    'iframeselecttab',
    'navtabdata',
    'systemname'
   ])
  },
  mounted(){
   const _this = this

   // 1、监听添加iframe中tab的广播
   this.$root.bus.$on('addiframetab', function (item) {

    // _this.tabslist.push(item)
    // _this.selecttabcode = item.tag
    _this.$store.commit(mainconst.m_iframe_push_tab, item)
    _this.$store.commit(mainconst.m_iframe_change_selectcode, item.tag)
   })

   // 2、监听切换iframe中tab的广播
   this.$root.bus.$on('changeiframetab', function (tag) {
    _this.$store.commit(mainconst.m_iframe_change_selectcode, tag)

   })
   // 3、监听删除iframe中tab的广播
   this.$root.bus.$on('deleteiframetab', function (obj) {
    // 1、删除iframe中的指定tab页面
    _this.$store.commit(mainconst.m_iframe_delete_tab, obj)
    // _this.tabslist = _this.tabslist.filter(tab => tab.tag !== obj.tag)

    // 2、如果删除的一级tab不是当前激活的一级tab,tabstemeplate中的一级tab删除事件已经在vuex中删除了,不需要做路由跳转操作了
    let index = obj.index
    for (let i = 0; i < _this.navtabdata.length; i++) {
     if (_this.navtabdata[i].active) {
      return
     }
    }

    // 3、如果删除的一级tab是当前激活的一级tab,
    const con = _this.navtabdata[index - 1] || _this.navtabdata[index]
    let url = `/${_this.systemname}`
    if (con) {
     // 还有其他的一级tab,就赋值其他的一级tab的url,探后跳转
     url = con.url
     con.active = true

     // 如果还有其他一级的tab,那么还要判断跳转的页面是不是iframe
     if (url.tolowercase().indexof("/iframe") == 0) {
      // 如果是iframe页面,显示iframe,广播iframe的切换tab切换事件,路由进行跳转
      _this.$store.commit(mainconst.m_show_iframe)
      _this.$root.bus.$emit("changeiframetab", url.slice(8))

     } else {
      // 如果不是iframe页面,隐藏iframe,路由进行跳转
      _this.$store.commit(mainconst.m_hide_iframe)
      // _this.$store.commit(mainconst.m_update_navtabdata, {navindex: index})
     }
    }
    else {
     // 没有其他的一级tab,直接隐藏iframe,跳首页
     _this.$store.commit(mainconst.m_hide_iframe)
    }

    _this.$router.push(url)
   })
  }
 }
</script>

之后的ifram组件的显示隐藏和tab切换,都是通用vuex和bus事件广播实现的

Vue集成Iframe页面的方法示例

/*
 * mainconst.js
 **/


/*****************************getter常量****************************************/
export const g_get_navtabdata = 'g_get_navtabdata'

/*****************************mutations常量*************************************/
// 一级tab处理
export const m_push_navtabdata = 'm_push_navtabdata'
export const m_delete_navtabdata = 'm_delete_navtabdata'
export const m_update_navtabdata = 'm_update_navtabdata'

// iframe切换处理
export const m_show_iframe = 'm_show_iframe'
export const m_hide_iframe = 'm_hide_iframe'

// iframe添加,删除,选择处理
export const m_iframe_push_tab='m_iframe_push_tab'
export const m_iframe_delete_tab='m_iframe_delete_tab'
export const m_iframe_change_selectcode='m_iframe_change_selectcode'

// 设置全局系统变量
export const m_set_systemname = 'm_set_systemname'

/*****************************actions常量***************************************/
// export const a_request_data = 'a_request_data'

/*
 * mainmodule.js
 **/

import * as mainconst from './mainconst.js'

export default {
 state: {
  // 一级tab导航数据集合
  navtabdata: [],
  // 进入的主系统前缀
  systemname:'',
  // 控制路由同级的iframe的显示隐藏
  showiframe: false,
  // iframe页面中的选中页签的code值
  iframeselecttab:'',
  // iframe页面的tab数据集合
  iframetabdata:[]

 },
 getters: {
  [mainconst.g_get_navtabdata](state, getters){
   return state.navtabdata
  }
 },
 mutations: {
  // 一级tab处理
  [mainconst.m_update_navtabdata](state, payload){
   const index = payload.navindex
   state.navtabdata.foreach((item)=> {
    item.active = false
   })

   // 当你利用索引直接设置一个项时是不能触发视图的从新渲染的,下面是老方法和解决办法
   // state.navtabdata[index].active=true
   let newitem = object.assign({}, state.navtabdata[index], {active: true})
   // console.log(newitem, 'store newitem')
   state.navtabdata.splice(index, 1, newitem)
  },
  [mainconst.m_push_navtabdata] (state, payload) {
   state.navtabdata.push(payload)
  },
  [mainconst.m_delete_navtabdata] (state, payload) {
   state.navtabdata.splice(payload.navindex, 1)
  },
  // iframe显示隐藏切换处理
  [mainconst.m_show_iframe] (state, payload) {
   state.showiframe = true
  },
  [mainconst.m_hide_iframe] (state, payload) {
   state.showiframe = false
  },
  // iframe添加,删除,选中处理
  [mainconst.m_iframe_push_tab] (state, payload) {
   state.iframetabdata.push(payload)
  },
  [mainconst.m_iframe_delete_tab] (state, payload) {
   state.iframetabdata = state.iframetabdata.filter(tab => tab.tag !== payload.tag)
  },
  [mainconst.m_iframe_change_selectcode] (state, payload) {
   state.iframeselecttab=payload
  },
  // 设置全局system变量
  [mainconst.m_set_systemname] (state, payload) {
   state.systemname=payload
  }
 },
 actions: {
  // actions的最终功能是修改state,但是它不直接修改state,而是调用mutations
  // async [aboutconst.a_request_data]({dispatch,commit}) {
  //  commit(aboutmutations.request_loading)
  //  await service.getmovielistdata('{"movietype":"in_theaters","pageindex":2,"start":0,"count":10}')
  //  console.log(333333)
  //  await function(){settimeout(function () {
  //   commit(aboutmutations.request_faild)
  //  },6000)}()
  //  console.log(66666)
  // }

  // actions的最终功能是修改state,但是它不直接修改state,而是调用mutations
  // async [aboutconst.a_request_data]({dispatch,commit}) {
  //  commit(aboutmutations.request_loading)
  //  await service.getmovielistdata('{"movietype":"in_theaters","pageindex":2,"start":0,"count":10}')
  //  console.log(333333)
  //  await function(){settimeout(function () {
  //   commit(aboutmutations.request_faild)
  //  },6000)}()
  //  console.log(66666)
  // }
 }
}

/*
 * 三级菜单的点击处理
 **/
<template>
 <!--三级菜单导航功能-->
 <div class="main-nav f14 clearfix" @mouseleave="funmenu.menuisshow=false">
  <div class="f_l lt-tab">
   <ul class="l-nav clearfix">
    <li class="main f_l">
     <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="f16 fun" @click="getmainmenu">功能导航</a>
     <div class="more-menu clearfix" v-show="funmenu.firstmenu.length&&funmenu.menuisshow">
      <!--一级导航-->
      <ul class="first-menu f_l">
       <li v-for="(item,index) in funmenu.firstmenu" @mouseover="clickbymenu($event,item,'firstmenu')">
        <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" :class="{active:item.active}" :index="index">{{item.resourcename}}</a>
       </li>
      </ul>
      <!--二级导航-->
      <ul class="next-menu f_l" v-show="funmenu.nextmenu.length">
       <li
        v-for="(item,index) in funmenu.nextmenu"
        @mouseover="clickbymenu($event,item,'nextmenu')"
        @click="clickmenujump(funmenu.nextmenu, item)"
       >
        <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" :class="{active:item.active}" :index="index">{{item.resourcename}}</a>
       </li>
      </ul>
      <!--三级导航-->
      <!--存在四级导航-->
      <div class="last-menu f_l dl" v-show="funmenu.lastmenu.length">
       <div v-for="(item,index) in funmenu.lastmenu" class="dt">
        <div v-if="item.childfuncs.length">
         <span>{{item.resourcename }}</span>
         <ul class="dd">
          <li v-for="(item,index) in item.childfuncs"
           @click="clickbymenu($event,item,'lastmenu')">
           <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >{{item.resourcename}}</a>
           <!--:class="{active:item.active}"-->
          </li>
         </ul>
        </div>
        <!--三级导航可点击-->
        <div v-else>
         <ul class="dd">
          <li @click="clickbymenu($event,item,'lastmenu')">
           <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >{{item.resourcename}}</a>
           <!--:class="{active:item.active}"-->
          </li>
         </ul>
        </div>

       </div>
      </div>
     </div>
    </li>
    <li class="nav-index f_l">
     <!--<router-link :to="'/'+$store.state.systemname">首页</router-link>-->
     <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="gohome">首页</a>
    </li>
   </ul>
  </div>
 </div>
</template>
<style scoped lang="scss">
 .main-nav {
  position: relative;
  height: 42px;
  line-height: 42px;
  background: #eee;
  border-bottom: 1px solid #ddd;
 }

 .main-nav a {
  color: #303e51;
  text-decoration: none;
 }

 .main-nav a:hover {
  color: #438eb9;
 }

 .main-nav .main {
  /*padding: 0 16px;*/
  text-align: center;
  border-right: 1px solid #ddd;
  position: relative;
  background: #eee;
  width: 122px;
 }

 .main-nav .main.active, .main-nav .main:hover {
  background: white;
 }

 .main-nav .more-menu {
  position: fixed;
  top: 84px;
  left: 0;
  max-height: 500px;
  bottom: 124px;
  z-index: 998;
  background: #fff;
  border: 1px solid #ddd;
  border-left: none;
  border-top: 0;
  overflow: hidden;
  box-shadow: 1px 1px 10px #ddd;
 }

 .main-nav .more-menu ul, .main-nav .more-menu .dl {
  text-align: left;
  overflow: auto;
 }

 .main-nav .more-menu a {
  font-size: 14px;
  color: #303e51;
  text-decoration: none;
 }

 .main-nav .more-menu a:hover, .main-nav .more-menu a.active {
  color: rgb(46, 167, 224);
 }

 .main-nav .more-menu .first-menu {
  height: 100%;
  border-right: 1px solid #ddd;
  box-shadow: -1px 0px 5px #ddd inset;
  /*width: 138px;*/
 }

 .main-nav .more-menu .first-menu li {
  height: 36px;
  line-height: 36px;
  margin: 0 15px 0 6px;
  min-width: 94px;
 }

 .main-nav .more-menu .first-menu a {
  display: block;
  background: url(../../asserts/images/home/main/icon_1.png) no-repeat 5px center;
  width: 100%;
  height: 100%;
  border-bottom: 1px solid #dddddd;
  padding-left: 20px;
  box-sizing: border-box;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  text-indent: 5px;
 }

 .main-nav .more-menu .first-menu a.active, .main-nav .more-menu .first-menu a:hover {
  background: url(../../asserts/images/home/main/icon_2.png) no-repeat 5px center rgb(46, 167, 224);
  color: white;
  border: 0;
 }

 .main-nav .more-menu .next-menu {
  height: 100%;
  border-right: 1px solid #ddd;
  box-shadow: -1px 0px 5px #ddd inset;
  /*width: 138px;*/
  line-height: 14px;
 }

 .main-nav .more-menu .next-menu li:first-child {
  margin-top: 10px;
 }

 .main-nav .more-menu .next-menu li {
  margin-bottom: 16px;
  margin-left: 16px;
 }

 .main-nav .more-menu .next-menu li a {
  border-left: 2px solid transparent;
  padding-left: 10px;
  margin-right: 24px;
 }

 .main-nav .more-menu .next-menu li a:hover, .main-nav .more-menu .next-menu li a.active {
  border-left: 2px solid rgb(46, 167, 224);
 }

 .main-nav .more-menu .last-menu {
  height: 100%;
  min-width: 288px;
  line-height: 14px;
 }

 .main-nav .more-menu .last-menu .dt {
  margin-left: 16px;
  margin-top: 10px;
  span {
   color: #566678;
  }
 }

 .main-nav .more-menu .last-menu .dd {
  color: #7a8897;
  margin-top: 16px;
  margin-left: 4px;
  > li {
   margin-bottom: 16px;
   a {
    border-left: 2px solid transparent;
    padding-left: 6px;
    margin-right: 16px;
    &:hover, &.active {
     border-color: #2ea7e0;
    }
   }
  }
 }

 /*.main-nav .more-menu .last-menu dd a:hover,.main-nav .more-menu .last-menu dd a.active{*/
 /*border-left: 2px solid rgb(46,167,224);*/
 /*}*/
 .main-nav .main .fun {
  width: 100%;
  height: 100%;
  display: block;
 }

 .main-nav .main .fun:before {
  content: "";
  width: 18px;
  height: 18px;
  background: url("../../asserts/images/home/main/icon-all.png");
  background-position: -89px -7px;
  display: inline-block;
  margin-right: 10px;
  margin-top: 2px;
  vertical-align: text-top;
 }

 .main-nav .l-nav {
  z-index: 2;
 }

 .main-nav .nav-index {
  width: 90px;
  text-align: center;
  position: relative;
  background: #eee;
 }

 .main-nav .nav-index:after {
  content: "";
  width: 8px;
  height: 40px;
  background: url(../../asserts/images/home/main/shadow-l.png);
  position: absolute;
  top: 2px;
  left: 90px;
 }

 .main-nav .lt-tab {
  position: absolute;
  left: 0;
  z-index: 2;
  border-bottom: 1px solid #ddd;
 }

 /*tab--------*/
 .main-nav .ct-tab {
  position: absolute;
  z-index: 1;
  left: 213px;
  width: 10000000px;
 }

 .main-nav .ct-tab .ct-ul {

 }

 .main-nav .ct-tab .ct-ul li {
  position: relative;
  float: left;
 }

 .main-nav .ct-tab .ct-ul li a {
  height: 24px;
  line-height: 24px;
  margin: 9px 0;
  min-width: 90px;
  /*max-width: 190px;*/
  border-right: 1px solid #ddd;
  display: block;
  text-align: center;
  position: relative;
 }

 .main-nav .ct-tab .ct-ul li a i {
  display: none;
 }

 .main-nav .ct-tab .ct-ul li a i {
  display: none;
 }

 .main-nav .ct-tab .ct-ul li a .content {
  display: block;
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
 }

 .main-nav .ct-tab .ct-ul li a:hover {
  z-index: 1;
 }

 .main-nav .ct-tab .ct-ul li:first-child a:hover, .main-nav .ct-tab li:first-child a.active {
  margin-left: 0;
  margin-right: 0;
 }

 .main-nav .ct-tab .ct-ul li a:hover, .main-nav .ct-tab li a.active {
  max-width: 250px;
  display: block;
  text-align: center;
  position: relative;
  border: 0;
  margin: 0 -20px;
  margin-top: 4px;
  color: black;
  padding: 0;
 }

 .main-nav .ct-tab .padding {
  width: auto;
  padding: 0 16px;
 }

 .main-nav .ct-tab .ct-ul li a:hover > i, .main-nav .ct-tab .ct-ul li a.active > i {
  display: inline-block;
  width: 34px;
  height: 37px;
  float: left;
 }

 .main-nav .ct-tab .ct-ul li a:hover .line-l {
  background: url(../../asserts/images/home/main/line_left.png) no-repeat;
 }

 .main-nav .ct-tab .ct-ul li a:hover .line-r {
  background: url(../../asserts/images/home/main/line_right.png) no-repeat;
 }

 .main-nav .ct-tab .ct-ul li a.active .line-l {
  background: url(../../asserts/images/home/main/line_sel_left.png) no-repeat;
 }

 .main-nav .ct-tab .ct-ul li a.active .line-r {
  background: url(../../asserts/images/home/main/line_sel_right.png) no-repeat;
 }

 .main-nav .ct-tab .ct-ul li a:hover .content, .main-nav .ct-tab li a.active .content {
  border-top: 1px solid #ddd;
  float: left;
  line-height: 36px;
  min-width: 60px;
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: rgb(245, 245, 245);
 }

 .main-nav .ct-tab .ct-ul li a:hover .cha, .main-nav .ct-tab .ct-ul li a.active .cha {
  background: rgb(245, 245, 245);
  width: 20px;
  height: 36px;
  line-height: 36px;
  border-top: 1px solid #ddd;
  padding-left: 7px;
  color: #303e51;
 }

 .main-nav .ct-tab .ct-ul li a.active .content, .main-nav .ct-tab .ct-ul li a.active .cha {
  background: white;
 }

 .main-nav .ct-tab .ct-ul li a .cha {
  color: #eee;
 }

 .main-nav .ct-tab .ct-ul li a .cha:hover {
  color: black;
 }

 .main-nav .ct-tab .ct-ul li a.active {
  z-index: 2;
 }
</style>
<script>
 import axios from 'axios'
 import { mapstate} from 'vuex'
 import * as mainconst from '@/store/mainconst.js'
 import config from '@/config/index.js'
 import storage from '@/utils/storage.js'
 export default{
  data(){
   return {
    funmenu: {
     // 一级菜单
     firstmenu: [],
     // 二级菜单
     nextmenu: [],
     // 三级菜单
     lastmenu: [],
     // 是否显示
     menuisshow: true
    }
   }
  },
  computed: mapstate({
   // 箭头函数可使代码更简练
   funcmenulist: state => state.funcmenulist,
  }),
  methods: {
   // 跳转首页
   gohome(){
    // 跳转首页就关闭iframe
    this.$store.commit(mainconst.m_hide_iframe)
    this.$router.push(`/${this.$store.state.systemname}`)
   },
   // ★★★★★调用方法获取三级菜单列表★★★★★
   getmainmenu(){
    var _this = this
    if (this.funmenu.firstmenu.length) {
     this.funmenu.menuisshow = true
    } else {
     if (config.setting.funcmenu) {
      _this.funmenu.firstmenu = storage.getitem('hivescm.userauthor').menus.funcs
     } else {
      axios.get("data/menu_json.json")
       .then(function (res) {
        _this.funmenu.firstmenu = res.data.result.funcs
       })
     }
    }
   },
   // 点击菜单展开下一级别列表事件
   clickbymenu(e, menuitem, level){
    let menulist = this.funmenu[level]
    switch (level) {
     case "firstmenu": {
      this.funmenu.nextmenu = this.getfirstandnextval(menulist, menuitem)
      this.funmenu.lastmenu = []
     }
      break
     case "nextmenu": {
      if (!menuitem.url.length) this.funmenu.lastmenu = this.getfirstandnextval(menulist, menuitem)
//      menuitem.url.length ? this.clickmenujump(menulist, menuitem) : this.funmenu.lastmenu = this.getfirstandnextval(menulist, menuitem)
     }
      break
     case "lastmenu": {
      this.clickmenujump(menulist, menuitem)
     }
      break
    }
   },
   // ★★★★★点击有url的菜单,跳转事件★★★★★
   clickmenujump(menulist, menuitem){
    if (!menuitem.url.length) return
    this.funmenu.menuisshow = false
    this.lastmenuchange(menulist, menuitem)
    let iframetabitem = {}
    // 1、路由跳转和iframe的显示隐藏
    if (menuitem.url.tolowercase().indexof("/") != 0 || menuitem.url.tolowercase().indexof("/iframe") == 0) {
     // 判断如果是iframe的url,显示iframe
     // 定义一个新的item对象,防止对象的引用
     iframetabitem = object.assign({}, menuitem)
     this.$store.commit(mainconst.m_show_iframe)
     // 待优化:应该有优化为手动赋值样式
     // (1)、此处利用router-view的特性,让一级tab变颜色
     // (2)、这个还是控制一级tab点击切换tab标签的重要因素
     // 因为原始的iframe的url已经改变,所以要保存到一个新的变量里面,如果已经有了就不需要在放了
     if (!menuitem.iframeurl) {
      menuitem.iframeurl = menuitem.url
      let userid = storage.getitem('hivescm.userauthor').id
      let token = storage.getitem('hivescm.userauthor').token
      iframetabitem.url = `${menuitem.url}?userid=${userid}&token=${token}`
     } else {
      let userid = storage.getitem('hivescm.userauthor').id
      let token = storage.getitem('hivescm.userauthor').token
      iframetabitem.url = `${menuitem.iframeurl}?userid=${userid}&token=${token}`
      console.log(iframetabitem.url)
//      iframetabitem.url = menuitem.iframeurl
     }
     menuitem.url = `/iframe/${menuitem.tag}`
     this.$router.push(`/iframe/${menuitem.tag}`)

    } else {
     // 判断如果是spa的url,隐藏iframe
     this.$store.commit(mainconst.m_hide_iframe)
     menuitem.url=`${menuitem.url}?permissionid=${menuitem.permissionid}`
     this.$router.push({path:menuitem.url,query:{permissionid:menuitem.permissionid}})
    }

    // 2、判断vuex中是否有重复的tab标签
    let navtabdata = this.$store.state.navtabdata
    for (let i = 0; i < navtabdata.length; i++) {
     if (navtabdata[i].url == menuitem.url) {
      // 已经有页签了,一级tab内容不重新渲染
      // 切换一级tab页签的激活样式
      this.$store.commit(mainconst.m_update_navtabdata, {navindex: i})
      // 从新计算一级tab位置
      this.$root.bus.$emit("clicklastmenu", menuitem)

      if (menuitem.url.tolowercase().indexof("/iframe") == 0) {
       // 如果已经iframe中的tab已经存在,那么触发iframe中的切换事件
//       this.$store.commit(mainconst.m_show_iframe)
       this.$root.bus.$emit("changeiframetab", menuitem.url.slice(8))
      }
      return
     }
    }

    // 3、向vuex中添加一级tab
    // 默认是否选中
    menuitem.active = true
    // 向一级tab中添加新的tab标签
    this.$store.commit(mainconst.m_push_navtabdata, menuitem)
    this.$store.commit(mainconst.m_update_navtabdata, {navindex: navtabdata.length - 1})
    // 向iframe中的tab添加页签
    this.$root.bus.$emit("addiframetab", iframetabitem)
   },
   // 清空导航属性值,确保再次点击无选中样式及不匹配数据
   lastmenuchange(menulist, menuitem){
    this.funmenu.firstmenu.foreach(function (item) {
     item.active = false
    })
    this.funmenu.nextmenu.foreach(function (item) {
     item.active = false
    })
    this.funmenu.lastmenu.foreach(function (item) {
     item.active = false
    })
    this.funmenu.nextmenu = []
    this.funmenu.lastmenu = []
   },
   // 增加选中样式及赋值下级菜单
   getfirstandnextval(menulist, menuitem){
    var childfuncs = []
    for (let i = 0; i < menulist.length; i++) {
     if (menulist[i].permissionid == menuitem.permissionid) {
      menulist[i].active = true
      childfuncs = menulist[i].childfuncs || []
     } else {
      menulist[i].active = false
     }
    }
    return childfuncs
   }
  }
 }
</script>

还要添加一个没用的路由,因为我们的锚记还要发生变化

Vue集成Iframe页面的方法示例

/*
 * iframe/router/index.js
 */
const systemnameprefix = "iframe_"
import maincontainer from '@/containers/maincontainer.vue'
import iframecomponent from '@iframe/containers/iframecomponent.vue'

export default [
 {
  path: '/iframe',
  component: maincontainer,
  children: [
   {path: ':tag', component: iframecomponent, meta: {requiresauth: true, keepalive: true}},
  ],
  meta: {requiresauth: true}
 }
]

/*
 * iframecomponent.vue,一个没用的vue文件,只是为了让浏览器中的锚记发生变化
 */

<template>
 <div v-if="iscache">
  <span>{{src}}</span>
 </div>
</template>
<style scoped lang="scss">
</style>
<script>
 export default{
  data(){
   return {
    iscache: true,
    src: ''
   }
  },
  created(){
  },
  mounted(){
   // 1、这个页面存在的意义就是在iframe页面切换的时候,路由可以跳转过去用,没有实际大的作用,但是得有这个页面
   // 2、iframe的tab页面的z-index比这个页面的高
   this.src=this.$route.params.tag
  }
 }
</script>

3. 思考点

虽然这样和iframe结合有点恶心,但是可以实现我们的思路

在这个功能的实现中我们用到了bus事件总线的广播和监听

  1. 其实这点我们是可以仔细思考的,因为大量的使用广播不可控,我们可以完全用vuex去实现,这点用了广播,确实偷懒了
  2. 广播并不是不推荐,而是要使用对场景,这点其实用广播确实不太好,不利于扩展,谁能猜出来会有哪些扩展?

大家不用关心具体的代码,如果你们遇到类似的问题,了解这个思路就可以了

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。