Vue集成Iframe页面的方法示例


Posted in Javascript onDecember 12, 2017

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. 广播并不是不推荐,而是要使用对场景,这点其实用广播确实不太好,不利于扩展,谁能猜出来会有哪些扩展?

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

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

Javascript 相关文章推荐
JSON 客户端和服务器端的格式转换
Aug 27 Javascript
基于jQuery的消息提示插件 DivAlert之旅(二)
Apr 01 Javascript
actionscript与javascript的区别
May 25 Javascript
图片在浏览器中底部对齐 解决方法之一
Nov 30 Javascript
仿中关村在线首页弹出式广告插件(jQuery版)
May 03 Javascript
javascript怎么禁用浏览器后退按钮
Mar 27 Javascript
javascript中的3种继承实现方法
Jan 27 Javascript
jQuery实现简单的DIV拖动效果
Feb 19 Javascript
用vue封装插件并发布到npm的方法步骤
Oct 18 Javascript
vue实现某元素吸顶或固定位置显示(监听滚动事件)
Dec 13 Javascript
解决vue-cli脚手架打包后vendor文件过大的问题
Sep 27 Javascript
微信小程序用户授权最佳实践指南
May 08 Javascript
微信小程序显示下拉列表功能【附源码下载】
Dec 12 #Javascript
Vue调试神器vue-devtools安装方法
Dec 12 #Javascript
微信小程序实现点击文字页面跳转功能【附源码下载】
Dec 12 #Javascript
javascript实现循环广告条效果
Dec 12 #Javascript
微信小程使用swiper组件实现图片轮播切换显示功能【附源码下载】
Dec 12 #Javascript
vue2.0 常用的 UI 库实例讲解
Dec 12 #Javascript
C#实现将一个字符转换为整数
Dec 12 #Javascript
You might like
用phpmyadmin更改mysql5.0登录密码
2008/03/25 PHP
Php 构造函数construct的前下划线是双的_
2009/12/08 PHP
浅析PHP程序防止ddos,dns,集群服务器攻击的解决办法
2013/06/18 PHP
PHP内核探索:变量存储与类型使用说明
2014/01/30 PHP
php实例分享之mysql数据备份
2014/05/19 PHP
linux下编译安装memcached服务
2014/08/03 PHP
PHP生成静态HTML文档实现代码
2016/06/23 PHP
多个datatable共存造成多个表格的checkbox都被选中
2013/07/11 Javascript
关于IE中getElementsByClassName不能用的问题解决方法
2013/08/26 Javascript
javascript实现倒计时N秒后网页自动跳转代码
2014/12/11 Javascript
js+html5通过canvas指定开始和结束点绘制线条的方法
2015/06/05 Javascript
js实现文字闪烁特效的方法
2015/12/17 Javascript
Active控件问题小结(附解决办法)
2016/06/09 Javascript
jquery easyUI中ajax异步校验用户名
2016/08/19 Javascript
详解从Node.js的child_process模块来学习父子进程之间的通信
2017/03/27 Javascript
JavaScript之filter_动力节点Java学院整理
2017/06/28 Javascript
layui实现动态和静态分页
2018/04/28 Javascript
vue 不使用select实现下拉框功能(推荐)
2018/05/17 Javascript
浅谈layui 数据表格前后台传值的问题
2019/09/12 Javascript
详解小程序BackgroundAudioManager踩坑之旅
2019/12/08 Javascript
[02:02]2018DOTA2亚洲邀请赛Mineski赛前采访
2018/04/04 DOTA
python高斯分布概率密度函数的使用详解
2019/07/10 Python
Python调用scp向服务器上传文件示例
2019/12/22 Python
python Timer 类使用介绍
2020/12/28 Python
HTML5 与 XHTML2
2008/10/17 HTML / CSS
TUMI新加坡官网:国际领先的商旅箱包品牌
2019/01/12 全球购物
Timberland法国官网:购买靴子、鞋子、衣服、夹克和配饰
2019/11/30 全球购物
校园安全检查制度
2014/02/03 职场文书
《长征》教学反思
2014/04/27 职场文书
关于青春的演讲稿500字
2014/08/22 职场文书
2014年路政工作总结
2014/12/10 职场文书
2015年驾驶员工作总结
2015/04/29 职场文书
民事撤诉申请书范本
2015/05/18 职场文书
2015年初三班主任工作总结
2015/05/21 职场文书
win11开机发生死循环重启怎么办?win11开机发生死循环重启解决方法
2022/08/05 数码科技
CSS使用SVG实现动态分布的圆环发散路径动画
2022/12/24 HTML / CSS