vue项目嵌套(vue2嵌套vue3)

阅读: 评论:0

vue项目嵌套(vue2嵌套vue3)

vue项目嵌套(vue2嵌套vue3)

实现思路

  1. 产品测评通过 iframe 将产品库加载进来。
  2. 创建 template.vue 中间页,使用path参数携带产品库url,并通过传递用户信息和路由信息实现产品库自动登陆。
  3. 使用 postMessgae API 实现父子项目间的数据通信。

实现步骤

  1. 创建 Store/template 模块,定义产品库相关数据。
// src/store/modlues/template.tsconst state = {sign: 'productLibrary', // 产品库路由标识routePath: '/template', // 产品库跳转中间页pathisFullFrame: false, // 是否设置产品库Iframe全屏NODE_ENV: v.NODE_ENV, // 环境变量ENV_URLS: {development: '127.0.0.1:3000',test: '',uat: '',production: '',},
};const mutations: MutationTree<any> = {SET_isFullFrame(state, val) {state.isFullFrame = val;},
}; 
  1. 创建 template.vue 中间跳转页路由。
// src/router/modules/page-productLibrary-router.ts{path: '/template',		// 对应Store/template.ts 的 routePathname: 'productLibrary',   // 对应Store/template.ts 的 signcn: '产品库',hidden: true,component: () => import('@/views/productLibrary/template.vue'),children: [],}, 
  1. 点击左侧菜单将符合条件的路由跳转到产品库。
// src/components/common/MenuItem.vue<script>methods: {navigateTo(e): void {const { frontPermission, url } = e;const { sign, routePath } = this.$plate;if (frontPermission.includes(sign)) {if (!url) return;this.$router.push({path: routePath,query: { path: url },});} else {if (this.$route.path === url) return;this.$router.push({ path: url });}},}
</script> 
  1. template.vue 监听路由并更新产品库路由,同时传递用户登陆信息实现自动登陆
// src/views/productLibrary/template.vue<div :class="{ wrapper: true, hidemenu: $plate.isFullFrame }"><iframe:src="src"frameborder="0"class="sub-frame"ref="frames"@load="frameLoad"></iframe>
</div><script lang="ts">@Component
export default class Index extends Vue {@Ref() readonly frames;src: string = ''; // 产品库跳转路由// 监听路由,更新产品库路由@Watch('$route')toggleRoute(data) {this.$nextTick(() => {this.frameLoad();});}frameLoad() {const { path = '' } = this.$route.query;const auth = Item('auth') || '';if (!path || !auth) return;this.setSrc(path); // 设置产品库跳转路由const productLibraryRoutes = Routes(); // 过滤产品库路由const permission = {auth,path,userInfo: Item('userInfo'),routes: productLibraryRoutes[0].childPermissionResList,};// 传递用户登陆信息实现自动登陆tWindow.postMessage(permission, '*');}getRoutes() {const localRoutes = Item('routes') || '';if (!localRoutes) return '';const { sign } = this.$plate; // 产品库跳转路由标识const routes: any[] = JSON.parse(localRoutes) || [];return routes.filter((i) => {return i.frontPermission === sign &amp;&amp; i.childPermissionResList;});}setSrc(path) {const { NODE_ENV, ENV_URLS } = this.$plate;const domain = ENV_URLS[NODE_ENV];if (path &amp;&amp; domain) this.src = `${domain}${path}`;}
}
</script> 
  1. 产品库获取登陆信息及路由信息进行模拟登陆操作。
// index.html<body><div id="app"></div><script type="module" src="/src/main.ts"></script><script>window.addEventListener('message',function (event) {const {data} = eventif (data.auth) {window.localStorage.setItem('auth', data.auth)window.localStorage.setItem('routes', JSON.utes))window.localStorage.setItem('userInfo', data.userInfo)window.localStorage.setItem('path', data.path)}},false,)</script>
</body>// src/router/routerGuards.ts
export function createRouterGuards(routers: Router) {routers.beforeEach(async (to, _, next) => {const isFrame = JSON.Item('isFrame') || '') // 是否是 iframe 加载if (!isFrame) {// 正常登陆操作} else {const hasToken = Item('auth') || ''const { addRouter } = store.state.globalif (hasToken &amp;&amp; addRouter) {next()return}localStorage.setItem('auth', Item('auth') || '')await storemit('global/setRoutes', JSON.Item('routes') || ''))await storemit('global/setUserInfo', JSON.Item('userInfo') || ''))// 路由添加/标记storemit('global/isAddRouter', true)const getNewRouter = s['global/getNewRouter']getNewRouter.forEach((route: Iroute) => {routers.addRoute(route)})const path = Item('path')to.path = pathconst newTo = {...to,name: to.name || undefined,}next({ ...newTo, replace: true })}})
} 
  1. 产品库向产品测试进行通信
// src/utils/template.ts// ifarame 内嵌时向产品测评窗口进行通信事件定义
const source = 'productLibrary' // 产品库跳转路由标识const posMessage = function (config) {const message = Object.assign({ source }, config)return new Promise((resolve) => {top.postMessage(message, '*')resolve(true)})
}// 是否设置全屏遮罩
export function postFrameCover(val) {const config = {fnName: 'setIframeCover',params: val,}return posMessage(config)
}// 跳转产品测评页面
export function postTopRouter(path) {if (!path) returnconst config = {fnName: 'setRoute',params: path,}return posMessage(config)
} 

问题总结及解决方案

左侧菜单路由高亮状态

展示产品库页面时,对应左侧菜单路由要相应高亮选中。
在监听路由跳转时,判断当跳转产品库页面时,取 query 中的 path 字段为 url 做高亮处理。

// src/components/Nav.vue<script>
@Watch('$route', { immediate: true })handlerRouteChange(to: Route): void {this.active = to.path;this.setProductRoute(to); // 判断产品库路由}setProductRoute(to) {const { name = '', query = {} } = to;const { sign } = this.$plate; // 产品库跳转路由标识const isProductLibRoute = name === sign &amp;&amp; query.path;if (isProductLibRoute) {this.active = query.path;}}
</script> 

产品测评面包屑导航页面路径

展示产品库页面时,对应上方面包屑导航要显示正确的路由名称。
在监听路由跳转时,判断当跳转产品库页面时,取 query 中的 path 字段为 url 做高亮处理。

// src/components/common/BaseHeard.vue<script>
@Watch('$route')$routeWatch(to: Iobj) {Bar(to);}getBar(route) {let pathName = RoutePath(route);let name = '';let barList: Array<Iobj> = [];let pathArr = pathName.split('/').filter((_) => _);let newArr = [...NewRouter,...(this.$router as any).utes,];for (let i of pathArr) {name = name + `/${i}`;for (let j of newArr) {if (j.path === name) {barList.push({cn: j,path: j.path,});break;}}}this.arr = barList;}// 获取当前路由pathgetRoutePath(route) {let { path: pathName, query } = route;const { routePath } = this.$plate;// 如果产品库的路由,修改为取query下的path为路由名称if (pathName === routePath) {const { path = '' } = query;if (path) return path;} else {return pathName;}}
</script> 

Dialog弹出窗遮罩覆盖

当点击弹窗时,通知父窗口,同步修改外层样式。

// 产品库
<el-button @click="handleMask()">测试弹窗</el-button><script>
import { postFrameCover } from '@utils/template'
handleMask() {postFrameCover(true).then(() => {this.showDialog = true})
}
</script>// 产品测评 template.vue
setIframeCover(val) {this.$storemit('template/SET_isFullFrame', val);
}// 产品测评 App.vue
// 修改左侧菜单的z-index,使遮罩在最顶层
<nav class="nav" :class="{ hidemenu: $plate.isFullFrame }"><app-nav />
</nav>.hidemenu {background: rgba(0, 0, 0, 0.5);z-index: 100;
}// 产品测评 template.vue
<div :class="{ wrapper: true, hidemenu: $plate.isFullFrame }"><iframe:src="src"frameborder="0"class="sub-frame"ref="frames"@load="frameLoad"></iframe>
</div>.hidemenu {background: rgba(0, 0, 0, 0.5);z-index: 100;
} 

产品库子项目跳转产品测评页面

// 产品库
<el-button type="primary" @click="handleArticle()">跳转产品测评文章详情</el-button><script>
import { postTopRouter } from '@utils/template'
handleArticle() {const route = {path: '/article/articleAdd',query: {id: '795964024911646720',},}postTopRouter(route)
}
</script> 

产品库判断当前项目是在iframe中还是web中

// index.html
<head><script>// 判断是在iframe还是weblet isFrame = falseif (window.frames.length != parent.frames.length) isFrame = truewindow.localStorage.setItem('isFrame', isFrame)</script>
</head> 

本文发布于:2024-02-01 18:53:15,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170678479538734.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:嵌套   项目   vue
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23