Skip to main content
  1. Blogs/
  2. 前端开发/
  3. amis/
  4. wujie/

·211 words·1 min
Table of Contents

这是我们的菜单路由数据结构:

准确获取页面 html
#

如果没有配置,则尝试 option.url 地址获取 html 内容,但可能一些环境配置差异,会导致访问不到 index.html

通常我们使用 vue2/cli 的项目 devServer 会这样配置:

module.exports = defineConfig({
	devServer: {
		//...
		proxy: {
		}
	}
})

当在微前端中,我们通常设置了 publicpath,会导致访问 http://localhost:8001/subApp/[subAppName]/[history path] 路径时出现 Cannot GET /subApp/[subAppName]/[history path],这样的情况你可以这样解决:

module.exports = defineConfig({
	devServer: {
		//...
		proxy: {
		},
		historyApiFallback: {
			index: '/[subAppName]/[history path]/index.html'
	    },
	}
})

但如果不熟悉这项配置,可能你需要特别设置 html 获取方式:

startApp({
  url,
  html: fetchHtml(remoteEntry),
  // ...
})
export const fetchHtml = (htmlUrl) => {
  return fetch(htmlUrl, {
    headers: {
      Accept: 'text/html',
    },
  })
    .then((response) => {
      if (response.status >= 400) {
        throw new Error('加载异常' + response.status)
      }
      return response.text()
    })
    .catch((e) => {
      return Promise.reject(e)
    })
}

route.component 设置
#

我们路由会分层级,比如 parent 会有 LayoutCompent 构成布局,具体 child 会在 渲染。

在动态路径中,由于子应用路由要交给他自己路由体系,所以需要在主应用中关闭子路由渲染逻辑:

<div id="micro-app-container" v-if="isSubAppFirstLoad">正在加载子应用</div>
<router-view :key="key" v-else />

主应用面包屑的控制
#

由于子应用中路由的跳转需要在主应用同步展开一排面包屑,目前想到的策略是在子应用中拦截所有路由变动,并通过 wujie event 通知主应用,主应用发起一次 $router.push 方法,从而将面包屑 UI 重新激活。

子应用路由变化:

router.beforeEach((to, from, next) => {
	window.$wujie?.bus.$emit("wujie-route-change", to);
})

主应用通过 cachedSubAppViews 标识控制是否加载过 wujie 子应用,同时再根据 reloadSubAppViews 判断子应用内部路由的变化:

bus.$on('wujie-route-change', (to) => {
	// 主应用还未加载过子应用
	if (!this.cachedSubAppViews.includes(to.name)) {
	  // 主应用路由跳转子应用to路由,设定开关,防止重新再次加载 loadSubApp(更新bms面包屑菜单)
	  if (!this.reloadSubAppViews.includes(to.name)) {
		this.reloadSubAppViews.push(to.name)
		this.$router.push({ path: to.path, query: to.query })
	  }
	} 
})

当满足上述条件后,发起主应用路由跳转,由于主应用根本不存在此应用,则在路由 watch 的地方再结合 reloadSubAppViews 跳过路由渲染逻辑:

watch: {
	$route(newVal) {
	  // 子应用内部路由组件渲染后,不再做子应用加载,但要重置 reloadSubAppViews
	  if (this.reloadSubAppViews.includes(newVal.name)) {
		const index = this.reloadSubAppViews.indexOf(newVal.name)
		this.reloadSubAppViews.splice(index, 1)
		return
	  }
	  if (newVal.meta.isSubApp) {
		setTimeout(() => {
		  // 确保 this.$route 更新完毕
		  this.loadSubApp()
		}, 0)
	  }
	},
},