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>
    <!--路由渲染的功能模塊區域-->
    <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

            // 一、監聽添加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)
            })

            // 二、監聽切換iframe中tab的廣播
            this.$root.bus.$on('changeIframeTab', function (tag) {
                _this.$store.commit(mainConst.M_IFRAME_CHANGE_SELECTCODE, tag)

            })
            // 三、監聽刪除iframe中tab的廣播
            this.$root.bus.$on('deleteIframeTab', function (obj) {
                // 一、刪除iframe中的指定tab頁面
                _this.$store.commit(mainConst.M_IFRAME_DELETE_TAB, obj)
                // _this.tabsList = _this.tabsList.filter(tab => tab.tag !== obj.tag)

                // 二、若是刪除的一級tab不是當前激活的一級tab,TabsTemeplate中的一級tab刪除事件已經在vuex中刪除了,不須要作路由跳轉操做了
                let index = obj.index
                for (let i = 0; i < _this.navTabData.length; i++) {
                    if (_this.navTabData[i].active) {
                        return
                    }
                }

                // 三、若是刪除的一級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 = '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:;" 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:;" :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:;" :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:;">{{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:;">{{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:;" @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 = {}
                // 一、路由跳轉和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}})
                }

                // 二、判斷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
                    }
                }

                // 三、向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 '@/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(){
            // 一、這個頁面存在的意義就是在iframe頁面切換的時候,路由能夠跳轉過去用,沒有實際大的做用,可是得有這個頁面
            // 二、iframe的Tab頁面的z-index比這個頁面的高
            this.src=this.$route.params.tag
        }
    }
</script>

3. 思考點

  • 雖然這樣和iframe結合有點噁心,可是能夠實現咱們的思路
  • 在這個功能的實現中咱們用到了bus事件總線的廣播和監聽
    • 其實這點咱們是能夠仔細思考的,由於大量的使用廣播不可控,咱們能夠徹底用vuex去實現,這點用了廣播,確實偷懶了
    • 廣播並非不推薦,而是要使用對場景,這點其實用廣播確實不太好,不利於擴展,誰能猜出來會有哪些擴展?
  • 你們不用關心具體的代碼,若是大家遇到相似的問題,瞭解這個思路就能夠了

4. 參考和引用

5. 特別感謝

  • 公司的小夥伴

6. 免責說明

  • 本文檔中的部份內容摘自網上的衆多博客,僅做爲本身知識的補充和整理,並分享給其餘須要的coder,不會用於商用。
  • 由於不少博客的地址看完沒有及時作保存,因此不少不會在這裏標明出處,很是感謝各位大牛的分享,也但願你們理解。
  • 若是原文做者感受不適,能夠及時聯繫我shiguoqing999@163.com,我將及時刪除爭議部份內容

7. 追責聲明

  • 若有大段引用超過全文50%的內容,請在文檔結尾標明原文出處:龍馬行空-石國慶-朱庇特-https://my.oschina.net/u/1416844/blog,不然將視爲抄襲,予以法律追究,請各位尊重我的知識產權。
相關文章
相關標籤/搜索