Vue 跨工程的路由整合

       最近在开发过程中,有个需求是在自己开发的应用中(以后简称:主应用)挂载第三方的页面应用(以后简称三方应用),大多数情况下,自己工程引入第三方工程页面用的是iframe嵌套,简单快捷,但是上下文处理、事件交互等方面并不是特别方便,于是就尝试另外的解决方案,当我看到vue的路由守卫,就知道问题该如何解决,大致思路如下:

利用路由独享的守卫beforeEnter,在跳转到第三方相关页面前,必定经过beforeEnter路由函数,然后我们在这个路由函数写我们逻辑,区别这个url是我们需要的第三方url还是错误的url,如果是我们需要url地址则会加载我们需要的第三方的js,加载三方应用js的时候,调用主应用中我们声明的接口(一个全局函数),然后把第三方的路由加载到我们主应用上,这里的两个应用都是webpack打包后,让我们实战吧。

1、主应用路由代码,位置:@/src/router/index.js,这里有个知识点,这个地方路由规则中'*'的优先级要低于其它路由规则,比如说,要访问index/coma这个url,因为已经匹配到第一个路由规则,所以不会进入beforeEnter

......
import { handleRoute } from '../utils/route_combine'
import Layout from '@/layout/index.vue'

export const THIRD_PARTY_THOKEN = 'third'

const routes = [
  {
    path: '/index/coma',
    component: (resolve) => require(['@/views/components/com-a/index'], resolve)
  },
    ....
  {
    path: '404',
    component: (resolve) => require(['@/views/error-page/404'], resolve)
  },
  {
    path: '/third',
    name: THIRD_PARTY_THOKEN,
    component: Layout,
    children: []
  },
  {
    path: '*',
    async beforeEnter(to, from, next) {
      // 第三方业务线拦截
      const isService = await handleRoute(to, next, asyncRouter)
      // 非第三方业务线页面,走找不到
      if (!isService) {
        next('/404')
      }
    }
  }
]
export default new Router({
  routes
})

2、handleRoute函数代码,位置:@/src/utils/route_combine.js,声明一个三方应用配置,如果我们在handleRoute过程中,发现url属于三方应用的配置,则去加载三方应用的js

// let config = null;
const config = {
  thirdparty: {
    src: [
      'third/third-02/app.bundle.js' // 这个就是打包后的三方应用的js
    ],
    loaded: false
  }
}

// const getConfig = () => {
//   axios({
//     url: 'your-url',
//     method: 'get',
//     params: 'parameter'
//   }).then(data => {
//     config = data;
//   })
// }

// 加载第三方js
const loadScript = (src) => {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script')
    script.src = src
    script.async = true
    script.onerror = () => {
      reject()
    }
    script.onload = () => {
      resolve(true)
    };
    (document.head || document.body).appendChild(script)
  })
}

// 整合第三方路由
export const handleRoute = async(to, next, asyncRouter) => {
  const path = to.path || ''
  const paths = path.split('/')
  const serviceName = paths[1]
  // if (!config) {
  //   await getConfig()
  // }
  const cfg = config[serviceName]
  // 非业务线路由
  if (!cfg) {
    next()
    return false
  }
  if (cfg.loaded) {
    next()
    return true
  }
  for (let i = 0; i < cfg.src.length; i++) {
    await loadScript(cfg.src[i])
  }
  cfg.loaded = true
  next({ ...to, replace: true }) // 继续请求页面
  return true
}

3、主应用中声明的接口,位置:@/src/main.js,为了方便,直接在main.js中声明了

import router, { THIRD_PARTY_THOKEN } from './router'

......


const router = new Router({
  routes: constRouter
})

const registerApp = (routes) => {
  if (routes) {
    routes.forEach(route => {
// 添加一条新的路由记录作为现有路由的子路由
      router.addRoute(THIRD_PARTY_THOKEN, route)
    })
  }
}

// 声明注册路由的全局接口
window.mainApp = Object.assign(window.mainApp || {}, {
  Vue,
  router,
  ElementUI: Element,
  utils: {
    registerApp
  }
})

4、三方应用调用主应用声明的接口,位置:@/src/main.js

let { Vue, router, ElementUI } = window.dandelionApp;
import { routes, APP_NAME } from './router/index'
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
import '@/styles/index.scss' // global css
// Vue.use(ElementUI)
window.mainApp && window.mainApp.utils.registerApp(routes)
export default Vue;
console.log(Vue, router, APP_NAME, ElementUI)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值