Umi 使用 Vue:从安装预设到路由与运行时配置的完整指南
2026/9/14 20:31:39 网站建设 项目流程

Umi 使用 Vue:从安装预设到路由与运行时配置的完整指南

【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi

本篇指南以 Umi 官方文档 use-vue.en-US.md 为骨架,系统讲解如何在 Umi 框架中启用 Vue 3 开发模式,覆盖@umijs/preset-vue的安装与预设配置、配置式路由中的命名路由/重定向/别名、页面跳转 API,以及src/app.tsx中的运行时配置(router、onMounted、rootContainer)等关键主题。读完本文,你将掌握在 Umi 工程里完整搭建 Vue 应用、复用 Umi 既有构建与插件体系,并解决 Vue 场景下差异化配置问题的实战能力。

为什么在 Umi 中使用 Vue

Umi 本身是 React 社区的可扩展前端框架,但其插件化架构允许通过预设(Preset)将渲染层切换到其他框架。packages/preset-vue 正是这一能力的体现:它内部依赖 Vue 3(vue@3.2.45)、vue-router@4.1.6vue-loader以及@vitejs/plugin-vue等编译配套(见 preset-vue/package.json),并在此基础上复用 Umi 的路由约定、约定式目录、mock、代理等大量既有能力。

从源码结构看(preset-vue/src/index.ts),@umijs/preset-vue注册了vue这一配置项(zod.object({})校验,默认值为{}),并依次挂载四个子插件:

  • features/default:负责默认配置、别名与特性开关;
  • features/webpack:负责 Webpack 构建链路中的 Vue 编译;
  • features/tmpFiles:负责生成core/history.tscore/App.vue等临时文件;
  • features/vite:负责 Vite 构建链路中的 Vue 插件。

Umi Vue 的大部分配置与 React 相同,本文只列出 Vue 独有的配置。

启动方式:安装预设并启用 Vue

安装

在项目中安装@umijs/preset-vue作为开发依赖:

pnpm add @umijs/preset-vue -D

仓库内的 Vue 示例工程(如 examples/boilerplate-vue/package.json)正是将@umijs/preset-vueumivue@3.2.45一同列为依赖,脚本中可直接使用umi devumi buildumi preview等命令。

配置预设

.umirc.tsconfig/config.ts中把 preset 加入presets数组:

// .umirc.ts or config/config.ts export default { presets: [require.resolve('@umijs/preset-vue')], };

启用后,preset 内部会自动完成一系列切换。以 features/default.ts 为例,从源码可以看到以下关键行为:

  • 别名指向 Vue 构建产物vue被指向dist/vue.esm-bundler.jsdist/vue.runtime.esm-bundler.js(取决于api.userConfig.vue?.runtimeCompiler),vue-router优先解析项目自身安装的版本,否则回退到 preset 内置版本;
  • 特性开关注入:通过config.define设置__VUE_OPTIONS_API__: true__VUE_PROD_DEVTOOLS__: false
  • 禁用 React 专属能力fastRefresh被关闭、svgr被关闭,Babel 预设禁用presetReact并启用支持.vue扩展名的 TypeScript 处理(allExtensions: trueisTSX: true),同时额外引入@vue/babel-plugin-jsx以支持在.tsx中编写 Vue JSX;
  • 运行时插件 key 注册routeronRouterCreatedonAppCreatedonMounted被注册为运行时钩子(见下文「运行时配置」)。

构建层面,Webpack 链路(features/config/config.ts)通过vue-loader处理.vue文件、将.vue追加进resolve.extensions、并通过vue-loader/dist/pluginWebpack5注册插件;同时针对element-plus.mjs产物做了兼容处理。Vite 链路(features/vite/vite.ts)则在modifyViteConfig中注入@vitejs/plugin-vue@vitejs/plugin-vue-jsx两个插件,并透传api.config.vue作为插件配置。

路由:与 React 路由的差异部分

Vue 场景下 Umi 依然支持配置式路由,这里仅列出与 React 路由配置不同的部分。渲染层使用 Vue Router 4,@umijs/renderer-vue将 Umi 的routes配置转换为createRouter可消费的路由表(见 renderer-vue/src/routes.ts),并在 renderer-vue/src/browser.tsx 中以strict: true创建 router。

name:命名路由

除了path之外,可以为任意路由提供name

export default { routes: [ { path: '/user/:username', name: 'user', component: 'index' } ] }

要链接到一个命名路由,可以向router-link组件的to属性传递一个对象:

<router-link :to="{ name: 'user', params: { username: 'erina' }}"> User </router-link>

效果与命令式地调用router.push一致:

router.push({ name: 'user', params: { username: 'erina' } })

两种方式都会导航到路径/user/erina

redirect:重定向

重定向同样通过routes配置完成。下面的例子将/home重定向到/

export default { routes: [ { path: '/home', redirect: '/' } ] }

重定向的目标也可以是一个命名路由:

export default { routes: [ { path: '/home', redirect: { name: 'homepage' } } ] }

从源码看(renderer-vue/src/routes.ts),createClientRoute会优先处理redirect字段,将其原样透传给 Vue Router;而 renderer-vue/src/types.ts 中IRoute也把redirect定义为字符串类型。此外,若顶层路由的path未以/开头,渲染层会自动补全前导斜杠(见 routes.ts),避免触发 "Route paths should start with a /" 的运行时错误。

alias:别名

重定向是指用户访问/home时,URL 会被替换为/再匹配到/;而别名(alias)是指用户访问/home时,URL 仍然是/home,但会被匹配为用户正在访问/

对应的路由配置为:

export default { routes: [ { path: '/', component: 'index', alias: '/home' } ] }

通过别名,你可以自由地将 UI 结构映射到任意 URL,而不受配置嵌套结构的限制。使别名以/开头,可以将嵌套路径中的路径变成绝对路径;甚至可以把两者结合起来,用一个数组提供多个别名:

export default { routes: [ { path: '/users', component: 'users', routes: [ // 为这 3 个 URL 呈现 UserList // - /users // - /users/list // - /people { path: '', component: '/users/UserList', alias: ['/people', 'list'] }, ] } ] }

页面跳转与导航组件

页面跳转:useRouter 与 useRoute

在 Vue 单文件组件中,可以从umi直接导入useRouteruseRoute进行编程式导航:

<script lang="ts" setup> import { useRouter, useRoute } from 'umi'; const router = useRouter() const route = useRoute() const onHello = () => { router.push({ name: 'search', query: { ...route.query, }, }) } </script>

这两个 API 由@umijs/renderer-vuevue-router重新导出(见 renderer-vue/src/index.ts),同时导出的还有RouterLinkRouterViewcreateRoutercreateWebHistorycreateWebHashHistoryuseLinkonBeforeRouteLeaveonBeforeRouteUpdate等常用成员,因此 Vue Router 的 Composition API 能力在 Umi 中开箱即用。

仓库中的示例工程也大量使用了这一方式,例如 examples/boilerplate-vue/pages/list.vue 中通过useRouter()调用router.push('/list/456')跳转详情页。

router-link

router-link用于在模板中声明式导航,与 Vue Router 官方用法一致,支持to、命名路由对象等写法。参见 examples/boilerplate-vue/layouts/index.vue 中的导航栏示例,其使用<router-link to="/">Home</router-link>等形式组织页面导航。

router-view

router-view用于渲染当前匹配的路由组件。Umi 会为 Vue 应用生成一个默认根组件core/App.vue,其内容即<router-view></router-view>(见 preset-vue/src/features/tmpFiles/tmpFiles.ts),布局组件内也可自行放置<router-view>渲染子路由,参见 examples/boilerplate-vue/layouts/index.vue。

运行时配置:通过 src/app.tsx 控制 Vue 行为

与 React 工程类似,Vue 工程可以通过在约定的src/app.tsxexport相应配置来控制 Vue 与 Vue Router 的运行时行为。preset 在 features/default.ts 中注册了routeronRouterCreatedonAppCreatedonMounted四个运行时 key;渲染层 renderer-vue/src/browser.tsx 则按固定顺序执行这些钩子:先通过applyPlugins收集router配置并createRouter,触发onRouterCreated,再createApp并触发onAppCreated,随后app.use(router)app.mount(rootElement),最后触发onMounted

router

导出router可以配置 Vue Router 的设置:

// src/app.tsx export const router: RouterConfig = { // @ts-ignore scrollBehavior(to, from) { console.log('scrollBehavior', to, from); }, };

RouterConfig类型由@umijs/renderer-vue提供,等价于Omit<RouterOptions, 'history' | 'routes'>(见 renderer-vue/src/index.ts),即historyroutes由 Umi 接管,其余 Vue Router 选项均可配置。示例工程 examples/boilerplate-vue/app.tsx 中还演示了linkExactActiveClass: 'is-active'等典型配置。

onMounted({ app, router })

onMounted是 Vue app 挂载成功后的回调,这里可以拿到approuter的实例,用于全局组件注册、路由拦截器等:

export function onMounted({ app, router }: any) { console.log('onMounted', app, router); app.provide('umi-hello', { h: 'hello', w: 'word', }); }

仓库示例在此基础上进一步展示了路由守卫的写法,见 examples/boilerplate-vue/app.tsx,其中在onMounted内通过router.beforeEach注册全局前置守卫。

onRouterCreated({ router }) 与 onAppCreated({ app })

除了文档中列出的routeronMounted,从 features/default.ts 与 renderer-vue/src/browser.tsx 的源码可以确认,运行时还额外支持两个钩子:

  • onRouterCreated:router 创建完成后触发,可在此时注册路由守卫或扩展 router;
  • onAppCreated:Vue app 创建完成后触发,此时尚未mount,最适合安装第三方插件。

examples/boilerplate-vue/app.tsx 展示了两个钩子的基础用法;而 examples/with-vue-pinia/app.tsx 则利用onAppCreated通过app.use(createPinia())集成 Pinia 状态管理,examples/with-vue-element-plus/app.tsx 通过同样的方式注册 Element Plus。

rootContainer(container)

rootContainer用于修改交给 Vue Router 渲染时的根组件。例如,在外面包裹一个父组件:

import { h } from 'vue' export function rootContainer(container) { return h(ThemeProvider, null, container); }

从渲染层实现看(renderer-vue/src/browser.tsx),rootContainer处于插件容器修饰链的最外层优先级(依次为innerProvideri18nProvideraccessProviderdataflowProviderouterProviderrootContainer),因此它拿到的container是最终即将渲染的组件树,适合做主题 Provider 等最外层包裹。

参考示例

以下仓库示例可直接运行、对照阅读:

  • examples/boilerplate-vue:Vue 基础脚手架,包含 layouts、pages、wrappers、mock、.vue.tsx(Vue JSX)混写、app.tsx运行时配置,并配套 smoke.cy.ts 端到端用例;
  • examples/with-vue-pinia:在 Umi Vue 中集成 Pinia;
  • examples/with-vue-element-plus:在 Umi Vue 中集成 Element Plus 组件库。

这三个工程的package.json均以@umijs/preset-vue为预设依赖,并可通过各自的dev/build脚本直接启动验证。

【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询