Vue集成Iframe页面
2019独角兽企业重金招聘Python工程师标准>>>
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"><TabPanev-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=>iframeTabDataimport {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.indexfor (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.urlcon.active = true// 如果还有其他一级的tab,那么还要判断跳转的页面是不是iframeif (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.navIndexstate.navTabData.forEach((item)=> {item.active = false})// 当你利用索引直接设置一个项时是不能触发视图的从新渲染的,下面是老方法和解决办法// state.navTabData[index].active=truelet 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"><liv-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(){// 跳转首页就关闭iframethis.$store.commit(mainConst.M_HIDE_IFRAME)this.$router.push(`/${this.$store.state.systemName}`)},// ★★★★★调用方法获取三级菜单列表★★★★★getMainMenu(){var _this = thisif (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 = []}breakcase "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)}breakcase "lastMenu": {this.clickMenuJump(menuList, menuItem)}break}},// ★★★★★点击有url的菜单,跳转事件★★★★★clickMenuJump(menuList, menuItem){if (!menuItem.url.length) returnthis.funMenu.menuIsShow = falsethis.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.urllet userId = storage.getItem('hivescm.userAuthor').idlet token = storage.getItem('hivescm.userAuthor').tokeniframeTabItem.url = `${menuItem.url}?userId=${userId}&token=${token}`} else {let userId = storage.getItem('hivescm.userAuthor').idlet token = storage.getItem('hivescm.userAuthor').tokeniframeTabItem.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,隐藏iframethis.$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.navTabDatafor (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 = truechildFuncs = 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(){// 1、这个页面存在的意义就是在iframe页面切换的时候,路由可以跳转过去用,没有实际大的作用,但是得有这个页面// 2、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,否则将视为抄袭,予以法律追究,请各位尊重个人知识产权。
转载于:https://my.oschina.net/u/1416844/blog/1587411
Vue集成Iframe页面相关推荐
- 了解一下iframe页面嵌入使用,轻松实现页面集成
前言 在跨域请求不同服务方或是兼容先前系统的页面时,你可能想利用AJAX从网页上下载HTML并粘贴到div中,这将带来不安全注入的问题. 此时,通过iframe页面嵌入可以很好地解决上述问题. 本文带 ...
- vue 中嵌入iframe页面
使用的是vue-element-admin. 需求 项目需求是在点击左边侧边栏的时候判断如果是外部的页面之后,将此页面在右侧打开,每打开一个,tagview中也会相应加上,当切换这些tagview时, ...
- vue中用iframe嵌套页面,点击返回实现真正的退回上一步功能
vue项目中需要嵌套第三方的页面,但是第三方页面中的网页没有返回按钮,如图所示:此为页面b,页面a为跳到b页面的前一个页面. 点击iframe嵌套页面跳转的第二个页面 要实现不管进入多少层iframe ...
- Node.js、Npm、MVVM模式、idea的vue集成
Node.js 简单的说 Node.js 就是运行在服务端的 JavaScript. Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台. Node.js是一个事件驱动 ...
- 如何使用Vue集成其它UI组件?如何阅读UI官网?移动端组件Vant实例教程(熬夜干货)
如何使用Vue集成其它UI组件 前言 一.Vant是什么? 二.基础环境准备 1.1 了解是根本 1.2 安装 1.3 引入组件 3.1 步骤一 3.2 步骤二 3.3 步骤三 二.事件绑定 2.1 ...
- SpreadJS与Vue集成,苏宁集团『极客办公』系统开发案例
"造极"如今已成为苏宁集团的年度核心关键词."造极"在具体工作上的体现,代表着苏宁不断追求极致的工匠精神,即对待每一个环节,都要严格要求.精益求精." ...
- vue用iframe播放海康视频
由于项目需要同时显示两个相机的视频,使用上一篇文章封装的组件无法完成,因为当时webVideoCtrl.js是直接定义在全局的,$相当于一整个项目的window,无论怎么使用都只能在第一次定义的dom ...
- vue集成Highcharts 云词图
vue集成Highcharts 云词图 最近接手一个需求,需要服务端统计词语,前端出一个云图. 记得很早之前在echarts看到过一个云词图,去翻一下echarts官网没翻到索性去Highcharts ...
- vue集成超图supermap-cesium实践
一.使用vue-cli创建vue工程 1,cmd进入文件夹20200305,创建名为vuesupermap的工程. 命令为:vue init webpack vuesupermap 2,进入项目根目录 ...
最新文章
- 定档12月22日!《黑客帝国4》王者归来,再掀矩阵革命
- ASP.NET Core微服务(七)——【docker部署linux上线】(RDS+API接口测试部分)
- LeetCode 02.两数相加
- 为GridView-Delete列添加确认对话框(2种方法)
- java statement 动态参数_java_web学习(九) PreparedStatement动态参数的引入
- easyui快速入门
- python编写程序输出诗句_python基于词向量的古诗生成器
- 打印日志文件并将其上传存到HDFS中
- 这15个PDF转化工具
- HFDS 常用命令 fsck 查看文件信息和block位置信息
- Linux安装与卸载Nginx
- Android聊天软件的开发(七)--聊天通信
- python网页登录钉钉_关于钉钉接口使用Python,Post 500报错
- 函数定义与调用,自己实现pow()函数对整数的运算
- php人事考勤系统,基于PHPMySQL的考勤系统
- java 时间表达式_【JAVA】Quartz中时间表达式的设置
- 图片点击放大,并显示浮层
- 一文读懂哈希时间锁的合约机制、改进方向与应用场景
- 计算机图形学:传统函数方法判定点在不规则封闭区域内的判定方法
- 从“数学归纳法”到理解
热门文章
- 不同分类算法的优缺点是什么?(值得推荐)
- 搜集了一些模型,精模低模都有
- 评审关上了你CVPR的门?这还有Rebuttal的窗,7个小技巧送上
- 苹果汽车高管几乎流失殆尽,一年损失7人,新年又有人被Meta挖走
- 60%收入来自海外,VC追着投资,这匹千里马如此回答“AI往何处去”
- 咱们程序员,能吵吵就别动手!现在靠说就可以编程,支持Java、Python等10种语言|免费...
- 比英伟达便宜4000元、功耗更低、游戏性能相同,AMD发布RX 6900 XT旗舰显卡
- 1种策略就能控制多类模型,华人大二学生提出RL泛化方法,LeCun认可转发 | ICML 2020...
- ssm中shiro的使用
- STM32F103--(二) GPIO实践