This article mainly introduces examples of how Vue integrates Iframe pages. The editor thinks it is quite good. Now I will share it with you and give it as a reference. Let’s follow the editor and take a look.
1. Project requirements
We will switch to the vue framework later. Before, some functional pages used jsp pages. Written, and our management system needs to support both the Vue URL and the jsp pages after these releases
The other thing is that when switching tabs back, the previously entered things still exist
System page screenshot
2. Implementation idea
In response to this problem, our initial implementation idea was to write a Common components of iframe, and then pass the URLs of different http pages to switch, but this does not satisfy the second point. We found that as long as we switch the route of vue, and then switch back to the http page, the src attribute in the iframe The page will be refreshed, and there is no way to retain things, so we have the following implementation idea
We added an iframeTemp component at the same level as vue's router-view, which is actually a tab component of elementUI, and then Hide the style of the tab component header under our menu bar
<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 'vuex' import iframeTemp from '@/containers/main/IframeTemplate.vue' export default { data() { return {} }, components: { iframeTemp }, computed: { ...mapState([ 'showIframe' ]) } } </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 '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>
The display, hiding and tab switching of the ifram component are all implemented by universal vuex and bus event broadcast
/* * 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> <!--三级菜单导航功能--> <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,'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> <!--三级导航--> <!--存在四级导航--> <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,'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> </p> <!--三级导航可点击--> <p 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> </p> </p> </p> </p> </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> </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 '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>
We also need to add a useless route because our anchor has to change
/* * 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> <p v-if="isCache"> <span>{{src}}</span> </p> </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. Thoughts
Although it is a bit disgusting to combine it with iframe, it can realize our idea
In the implementation of this function, we use the broadcast and monitoring of the bus event bus
In fact, we can think about this carefully, because the large-scale use of broadcasts is uncontrollable. We can completely use vuex to achieve this. Using broadcasts is indeed lazy
-
Broadcasting is not not recommended, but it must be used in the right scenario. In fact, using broadcasting is not very good and is not conducive to expansion. Who can guess what expansions there will be?
You don’t need to care about the specific code. If you encounter similar problems, just understand this idea.
The above is what I compiled for everyone. I hope that I will use it in the future. Helpful to everyone.
Related articles:
How to call vuex to store interface data in vue.js
How to implement a number matching game using javascript
The process of encapsulating and submitting data in the form
The above is the detailed content of How to implement integrated Iframe page using Vue. For more information, please follow other related articles on the PHP Chinese website!

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

Zend Studio 13.0.1
Powerful PHP integrated development environment

SublimeText3 English version
Recommended: Win version, supports code prompts!

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool