Skip to content

快速上手

TIP

推荐使用wot-starter作为参考,已经集成了@wot-ui/router@uni-helper/vite-plugin-uni-pages,可以直接使用,无需关心本章节配置。

配置路由

使用 @uni-helper/vite-plugin-uni-pages 生成路由表

ts
import { createRouter } from '@wot-ui/router'
// 从虚拟模块导入自动生成的路由信息
import { pages, subPackages } from 'virtual:uni-pages'

function generateRoutes() {
  const routes = pages.map((page: any) => {
    const newPath = `/${page.path}`
    return { ...page, path: newPath }
  })
  if (subPackages && subPackages.length > 0) {
    subPackages.forEach((subPackage: any) => {
      const subRoutes = subPackage.pages.map((page: any) => {
        const newPath = `/${subPackage.root}/${page.path}`
        return { ...page, path: newPath }
      })
      routes.push(...subRoutes)
    })
  }
  return routes
}

const router = createRouter({
  routes: generateRoutes() // 路由表信息
})
export default router

配置main.ts

ts
import { createSSRApp } from 'vue'
import App from './App.vue'
import router from './router'
export function createApp() {
  const app = createSSRApp(App)
  app.use(router)
  return {
    app
  }
}

配置pages.json

在pages.json中为页面路由指定name字段后,即可以使用name跳转

注意:此处定义的name字段必须全局唯一。

json
//  pages.json
{
  "pages": [{
      "path": "pages/home/Home",
      "name": "home", // 路由 name 用于命名路由的跳转
      "style": {
        "mp-alipay": {
          "allowsBounceVertical": "NO"
        },
        "navigationBarTitleText": "首页"
      }
    },
    {
      "path": "pages/login/Login",
      "name": "login",
      "style": {
        "mp-alipay": {
          "allowsBounceVertical": "NO"
        },
        "navigationBarTitleText": ""
      }
    },
    {
      "path": "pages/mine/Mine",
      "name": "mine",
      "style": {
        "navigationBarTitleText": "",
        "navigationBarBackgroundColor": "#E7F0FF"
      }
    }
  ],
  "tabBar": {
    "color": "#bfbfbf",
    "selectedColor": "#0165FF",
    "backgroundColor": "#ffffff",
    "list": [{
        "pagePath": "pages/home/Home",
        "iconPath": "static/icon_home.png",
        "selectedIconPath": "static/icon_home_selected.png",
        "text": "首页"
      },
      {
        "pagePath": "pages/mine/Mine",
        "iconPath": "static/icon_mine.png",
        "selectedIconPath": "static/icon_mine_selected.png",
        "text": "我的"
      }
    ]
  },
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarBackgroundColor": "#FFF",
    "backgroundColor": "#F8F8F8"
  }
}

配置自动按需导入(可选)

使用unplugin-auto-import可以实现API的自动按需导入,提升开发效率。

安装unplugin-auto-import

bash
npm i unplugin-auto-import --save-dev
bash
yarn add unplugin-auto-import -D
bash
pnpm add unplugin-auto-import -D

配置vite.config.ts

ts
// vite.config.ts
import { defineConfig } from 'vite'
import UniHelperPages from '@uni-helper/vite-plugin-uni-pages'
import uni from '@dcloudio/vite-plugin-uni'
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    UniHelperPages({
      dts: 'src/uni-pages.d.ts',
      subPackages: [
        'src/subPages',
        // 可以添加更多子包目录
      ],
      exclude: ['**/components/**/*'],
    }),
    uni(),
    AutoImport({
      imports: [
        'vue',
        '@vueuse/core',
        'pinia',
        'uni-app',
        {
          from: '@wot-ui/router',
          imports: ['createRouter', 'useRouter', 'useRoute']
        }
      ],
      dts: 'src/auto-imports.d.ts',
      eslintrc: {
        enabled: true,
        globalsPropValue: true
      }
    })
  ]
})

导航守卫示例

本项目中包含了完整的导航守卫示例,展示了如何使用路由守卫实现页面访问控制和导航日志记录:

ts
// src/router/index.ts
router.beforeEach((to, from, next) => {
  console.log('🚀 beforeEach 守卫触发:', { to, from })

  // 演示:基本的导航日志记录
  if (to.path && from.path) {
    console.log(`📍 导航: ${from.path} → ${to.path}`)
  }

  // 演示:对受保护页面的简单拦截
  if (to.name === 'demo-protected') {
    const { confirm: showConfirm } = useGlobalMessage()
    console.log('🛡️  检测到访问受保护页面')

    return new Promise<void>((resolve, reject) => {
      showConfirm({
        title: '守卫拦截演示',
        msg: '这是一个受保护的页面,需要确认才能访问',
        confirmButtonText: '允许访问',
        cancelButtonText: '取消',
        success() {
          console.log('✅ 用户确认访问,允许导航')
          next()
          resolve()
        },
        fail() {
          console.log('❌ 用户取消访问,阻止导航')
          next(false)
          reject(new Error('用户取消访问'))
        },
      })
    })
  }

  // 继续导航
  next()
})

router.afterEach((to, from) => {
  console.log('🎯 afterEach 钩子触发:', { to, from })

  // 演示:简单的页面切换记录
  if (to.path) {
    console.log(`📄 页面切换完成: ${to.path}`)
  }

  // 演示:针对 afterEach 演示页面的简单提示
  if (to.name === 'demo-aftereach') {
    const { show: showToast } = useGlobalToast()
    console.log('📊 进入 afterEach 演示页面')
    setTimeout(() => {
      showToast('afterEach 钩子已触发!')
    }, 500)
  }
})

说明:

  • useGlobalMessageuseGlobalToast 是本项目中的自定义工具函数,用于显示确认框和提示消息
  • 实际使用时,可以根据项目需求使用 uni-app 原生的 uni.showModaluni.showToast API

使用 uni-app 原生 API 的示例:

ts
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isAuthenticated()) {
    uni.showModal({
      title: '提示',
      content: '请先登录',
      success: (res) => {
        if (res.confirm) {
          next({ name: 'login' })
        } else {
          next(false)
        }
      }
    })
  } else {
    next()
  }
})

router.afterEach((to, from) => {
  if (to.meta.title) {
    uni.setNavigationBarTitle({ title: to.meta.title as string })
  }
})

Released under the MIT License.