首頁 web前端 js教程 使用Vue如何實現整合Iframe頁面

使用Vue如何實現整合Iframe頁面

Jun 21, 2018 am 11:43 AM

這篇文章主要介紹了Vue整合Iframe頁面的方法範例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧

1. 專案需求

我們切換為vue框架是後面的事情,之前還有一些功能頁面是用jsp頁面寫的,而我們的管理系統需要既支援Vue的url,又要支援這些發布之後的jsp頁面

#還有一個就是切換tab回來的時候之前輸入的東西還要存在

系統頁面截圖

2. 實作想法

針對這個問題,我們最開始的實作想法是寫了一個iframe的通用元件,然後把不同的http的頁面的url傳遞進來進行切換,但是這樣不滿足第二條,我們發現只要切換了vue的路由,然後再切回http的頁面,iframe中的src屬性的頁面就會從新刷新,沒有辦法保留住東西,於是就有了下面的實現思路

我們在vue的router-view同級別添加了一個iframeTemp組件,其實就是一個elementUI的tab組件,然後把tab組件的頭的樣式隱藏在我們選單列的下面

<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>
登入後複製

之後的ifram組件的顯示隱藏和tab切換,都是通用vuex和bus事件廣播實現的

/*
 * 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>
登入後複製

還要增加一個沒用的路由,因為我們的錨記還要改變

/*
 * 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. 思考點

雖然這樣和iframe結合有點噁心,但是可以實現我們的思路

在這個功能的實現中我們用到了bus事件總線的廣播和監聽

  1. 其實這點我們是可以仔細思考的,因為大量的使用廣播不可控,我們可以完全用vuex去實現,這點用了廣播,確實偷懶了

  2. 廣播不是不推薦,而是要使用對場景,這點其實用廣播確實不太好,不利於擴展,誰能猜出來會有哪些擴展?

大家不用關心具體的程式碼,如果你們遇到類似的問題,了解這個思路就可以了

上面是我整理給大家的,希望今後會對大家有幫助。

相關文章:

在vue.js中如何呼叫vuex儲存介面資料

使用javascript如何實作數字配對遊戲

在form表單中有關資料封裝並提交的程序

以上是使用Vue如何實現整合Iframe頁面的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

JavaScript難以學習嗎? JavaScript難以學習嗎? Apr 03, 2025 am 12:20 AM

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

如何實現視差滾動和元素動畫效果,像資生堂官網那樣?
或者:
怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? 如何實現視差滾動和元素動畫效果,像資生堂官網那樣? 或者: 怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? Apr 04, 2025 pm 05:36 PM

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

console.log輸出結果差異:兩次調用為何不同? console.log輸出結果差異:兩次調用為何不同? Apr 04, 2025 pm 05:12 PM

深入探討console.log輸出差異的根源本文將分析一段代碼中console.log函數輸出結果的差異,並解釋其背後的原因。 �...

前端開發中如何實現類似 VSCode 的面板拖拽調整功能? 前端開發中如何實現類似 VSCode 的面板拖拽調整功能? Apr 04, 2025 pm 02:06 PM

探索前端中類似VSCode的面板拖拽調整功能的實現在前端開發中,如何實現類似於VSCode...

See all articles