Maison  >  Article  >  interface Web  >  Comment implémenter une page Iframe intégrée à l'aide de Vue

Comment implémenter une page Iframe intégrée à l'aide de Vue

亚连
亚连original
2018-06-21 11:43:083562parcourir

Cet article présente principalement des exemples de la façon dont Vue intègre les pages Iframe. L'éditeur pense que c'est plutôt bien, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur pour y jeter un œil

1. Exigences du projet

Nous passerons au framework vue plus tard. Certaines pages fonctionnelles utilisaient des pages jsp auparavant. notre système de gestion doit prendre en charge à la fois l'URL Vue et les pages jsp après ces versions

L'autre chose est que lorsque vous revenez à l'onglet, les éléments que vous avez entrés auparavant existeront toujours

Capture d'écran de la page système

2. Idée de mise en œuvre

Pour résoudre ce problème, notre idée de mise en œuvre initiale était d'écrire un composant commun de iframe, puis transmettons les URL des différentes pages http pour basculer, mais cela ne satisfait pas au deuxième point. Nous avons constaté que tant que nous changeons l'itinéraire de vue, puis revenons à la page http, l'attribut src dans le. iframe La page sera actualisée, et il n'y a aucun moyen de conserver les choses, nous avons donc l'idée d'implémentation suivante

Nous avons ajouté un composant iframeTemp au même niveau que la vue routeur de vue, qui est en fait un composant tab d'elementUI, puis masquer le style de l'en-tête du composant tab sous notre barre de menu

<template>
 <!--路由渲染的功能模块区域-->
 <p 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>
 </p>
</template>
<style scoped lang="scss">
 .position {
  position: relative
 }

 .router-out-content {
  position: static;
 }
</style>
<script>
import { mapState } from &#39;vuex&#39;
import iframeTemp from &#39;@/containers/main/IframeTemplate.vue&#39;
export default {
 data() {
  return {}
 },
 components: {
  iframeTemp
 },
 computed: {
  ...mapState([
   &#39;showIframe&#39;
  ])
 }
}
</script>
/*
 * IframeTemplate.vue组件的内部
 **/

 <template>
 <!--iframe页面展示区域-->
 <p 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>
 </p>
</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 &#39;vuex&#39;
 import * as mainConst from &#39;@/store/mainConst.js&#39;
 export default{
  data(){
   return {
//    tabsList: [],
//    selectTabCode: &#39;&#39;
   }
  },
  computed: {
   ...mapState([
    &#39;iframeTabData&#39;,
    &#39;iframeSelectTab&#39;,
    &#39;navTabData&#39;,
    &#39;systemName&#39;
   ])
  },
  mounted(){
   const _this = this

   // 1、监听添加iframe中tab的广播
   this.$root.bus.$on(&#39;addIframeTab&#39;, 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(&#39;changeIframeTab&#39;, function (tag) {
    _this.$store.commit(mainConst.M_IFRAME_CHANGE_SELECTCODE, tag)

   })
   // 3、监听删除iframe中tab的广播
   this.$root.bus.$on(&#39;deleteIframeTab&#39;, 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>

L'affichage, le masquage et le changement d'onglet du composant ifram sont tous implémentés par Universal Vuex et Bus diffusion d'événements

/*
 * mainConst.js
 **/


/*****************************getter常量****************************************/
export const G_GET_NAVTABDATA = &#39;G_GET_NAVTABDATA&#39;

/*****************************mutations常量*************************************/
// 一级tab处理
export const M_PUSH_NAVTABDATA = &#39;M_PUSH_NAVTABDATA&#39;
export const M_DELETE_NAVTABDATA = &#39;M_DELETE_NAVTABDATA&#39;
export const M_UPDATE_NAVTABDATA = &#39;M_UPDATE_NAVTABDATA&#39;

// iframe切换处理
export const M_SHOW_IFRAME = &#39;M_SHOW_IFRAME&#39;
export const M_HIDE_IFRAME = &#39;M_HIDE_IFRAME&#39;

// iframe添加,删除,选择处理
export const M_IFRAME_PUSH_TAB=&#39;M_IFRAME_PUSH_TAB&#39;
export const M_IFRAME_DELETE_TAB=&#39;M_IFRAME_DELETE_TAB&#39;
export const M_IFRAME_CHANGE_SELECTCODE=&#39;M_IFRAME_CHANGE_SELECTCODE&#39;

// 设置全局系统变量
export const M_SET_SYSTEMNAME = &#39;M_SET_SYSTEMNAME&#39;

/*****************************actions常量***************************************/
// export const A_REQUEST_DATA = &#39;A_REQUEST_DATA&#39;
/*
 * mainModule.js
 **/

import * as mainConst from &#39;./mainConst.js&#39;

export default {
 state: {
  // 一级Tab导航数据集合
  navTabData: [],
  // 进入的主系统前缀
  systemName:&#39;&#39;,
  // 控制路由同级的Iframe的显示隐藏
  showIframe: false,
  // iframe页面中的选中页签的code值
  iframeSelectTab:&#39;&#39;,
  // 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, &#39;store newItem&#39;)
   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(&#39;{"movieType":"in_theaters","pageIndex":2,"start":0,"count":10}&#39;)
  //  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(&#39;{"movieType":"in_theaters","pageIndex":2,"start":0,"count":10}&#39;)
  //  console.log(333333)
  //  await function(){setTimeout(function () {
  //   commit(aboutMutations.REQUEST_FAILD)
  //  },6000)}()
  //  console.log(66666)
  // }
 }
}
/*
 * 三级菜单的点击处理
 **/
<template>
 <!--三级菜单导航功能-->
 <p class="main-nav f14 clearfix" @mouseleave="funMenu.menuIsShow=false">
  <p 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>
     <p 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,&#39;firstMenu&#39;)">
        <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,&#39;nextMenu&#39;)"
        @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>
      <!--三级导航-->
      <!--存在四级导航-->
      <p class="last-menu f_l dl" v-show="funMenu.lastMenu.length">
       <p v-for="(item,index) in funMenu.lastMenu" class="dt">
        <p v-if="item.childFuncs.length">
         <span>{{item.resourceName }}</span>
         <ul class="dd">
          <li v-for="(item,index) in item.childFuncs"
           @click="clickByMenu($event,item,&#39;lastMenu&#39;)">
           <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>
        </p>
        <!--三级导航可点击-->
        <p v-else>
         <ul class="dd">
          <li @click="clickByMenu($event,item,&#39;lastMenu&#39;)">
           <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>
        </p>

       </p>
      </p>
     </p>
    </li>
    <li class="nav-index f_l">
     <!--<router-link :to="&#39;/&#39;+$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>
  </p>
 </p>
</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 &#39;axios&#39;
 import { mapState} from &#39;vuex&#39;
 import * as mainConst from &#39;@/store/mainConst.js&#39;
 import config from &#39;@/config/index.js&#39;
 import storage from &#39;@/utils/storage.js&#39;
 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(&#39;hivescm.userAuthor&#39;).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(&#39;hivescm.userAuthor&#39;).id
      let token = storage.getItem(&#39;hivescm.userAuthor&#39;).token
      iframeTabItem.url = `${menuItem.url}?userId=${userId}&token=${token}`
     } else {
      let userId = storage.getItem(&#39;hivescm.userAuthor&#39;).id
      let token = storage.getItem(&#39;hivescm.userAuthor&#39;).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>

Ajoutez également un itinéraire inutile, car notre ancre changera également

/*
 * iframe/router/index.js
 */
const systemNamePrefix = "iframe_"
import MainContainer from &#39;@/containers/MainContainer.vue&#39;
import IframeComponent from &#39;@Iframe/containers/IframeComponent.vue&#39;

export default [
 {
  path: &#39;/iframe&#39;,
  component: MainContainer,
  children: [
   {path: &#39;:tag&#39;, component: IframeComponent, meta: {requiresAuth: true, keepAlive: true}},
  ],
  meta: {requiresAuth: true}
 }
]
/*
 * iframeComponent.vue,一个没用的vue文件,只是为了让浏览器中的锚记发生变化
 */

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

3. Réflexions

Bien que ce soit un peu dégoûtant de le combiner avec iframe, notre idée peut être réalisée

Dans cette fonction Dans la mise en œuvre, nous avons utilisé la diffusion et la surveillance du bus événementiel

  1. En fait, nous pouvons y réfléchir attentivement, car l'utilisation intensive de la diffusion est incontrôlable, et nous pouvons complètement utilisez vuex pour l'implémenter. La diffusion est vraiment paresseuse à cet égard

  2. La diffusion n'est pas recommandée, mais doit être utilisée dans le bon scénario. n'est pas propice à l'expansion. Quelqu'un peut-il m'aider à deviner quelles expansions il y aura ?

Vous n'avez pas besoin de vous soucier du code spécifique. Si vous rencontrez des problèmes similaires, comprenez simplement cette idée

Ce qui précède est ce que j'ai compilé pour tout le monde. J'espère que je l'utiliserai à l'avenir.

Articles connexes :

Comment appeler vuex pour stocker les données d'interface dans vue.js

Comment implémenter un jeu de correspondance de nombres en utilisant javascript

Le processus d'encapsulation et de soumission des données dans le formulaire

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn