1.main.ts(入口文件) --- 干什么的 & 常见改进
javascript
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from '@/store'
import * as Vant from 'vant'
import 'vant/lib/index.css'
const app = createApp(App)
app.use(Vant)
.use(store)
.use(router)
.mount('#app')
要点解释
-
createApp(App):用根组件App.vue创建应用实例(Vue3)。 -
.use(...):注册插件(router、store、UI库等)。顺序一般:全局插件 → 路由 → store(无强制,但某些插件会依赖顺序)。 -
.mount('#app'):把应用挂载到页面上的 DOM 元素(通常在index.html有一个<div id="app"></div>)。
常见改进/实践
-
在这里可以做全局错误处理、注册全局组件、设置全局指令、或把 Axios/请求库实例挂载到
app.config.globalProperties.$http。 -
推荐在生产环境中禁用某些 dev-only 插件或日志。
**示例:**设置全局错误捕获(简化)
javascript
app.config.errorHandler = (err, vm, info) => {
console.error('全局错误:', err, info)
}
2.index.ts(路由) --- 核心概念与扩展
javascript
const routes = [
{ path: '/', redirect: { name: 'Login' } },
{ path: '/login', name: 'Login', component: () => import('@/views/h5/Login.vue') },
{ path: '/home', name: 'Home', component: () => import('@/views/h5/Home.vue'), meta: { title: '首页', showInbreadcrumb: true }, children: [
{ path: 'self', name: 'Self', component: () => import('@/views/h5/Self.vue') }
]
}
]
const router = createRouter({ history: createWebHashHistory('/h5/'), routes })
要点解释
-
createWebHashHistory('/h5/'):开启 Hash 模式并设置 base 为/h5/(部署到子路径时常用)。 -
路由懒加载(
() => import(...)):首次访问才加载页面,减小首包体积。 -
嵌套路由:
/home/self由Home作为父布局渲染router-view展示子路由。 -
meta:自定义路由元信息(例如标题、需要权限、面包屑显示等)。
路由守卫(权限校验)
java
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
if (!token && to.path !== '/login') {
next('/login')
} else {
next()
}
})
改进建议
-
更严谨用法:
to.meta.requiresAuth来标记哪些路由需要鉴权,避免硬编码to.path !== '/login'。 -
加上
document.title = to.meta.title || '默认标题'来动态设置页面标题。 -
登录后把
redirect参数传回去:next({ path: '/login', query: { redirect: to.fullPath }}),登录成功后重定向回原页面。
3.index.ts(Vuex 状态管理) --- 读写方式与类型
javascript
export default createStore({
state: {
token: localStorage.getItem('token') && JSON.parse(localStorage.getItem('token')),
user: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))
},
getters: {
getToken: (state) => state.token
},
mutations: {
setToken(state, info) {
state.token = info || null
if (info) localStorage.setItem('token', JSON.stringify(info))
else localStorage.removeItem('token')
}
},
actions: {
logout({ commit }) {
commit('setToken', null)
commit('setLogedUser', null)
}
}
})
要点解释
-
state:存放全局数据(token、当前用户等)。 -
getters:计算/读取派生状态(类似组件的 computed)。 -
mutations:同步修改 state(必须是同步)。 -
actions:可以写异步逻辑(例如请求后 commit)。
使用示例
javascript
import { useStore } from 'vuex'
const store = useStore()
const token = store.state.token
store.commit('setToken', newToken)
store.dispatch('logout')
改进建议
-
使用 模块化(modules)把用户模块、产品模块分开,便于维护。
-
如果使用 TypeScript,给 state 定义接口并为
useStore提供类型。 -
考虑使用 Pinia(Vue 官方新推荐),API 更简洁、TypeScript 支持更好;但现有项目继续用 Vuex 也没问题。
简单 TypeScript 类型示例(概念性)
javascript
interface RootState {
token: string | null;
user: User | null;
}
declare module 'vuex' {
export function useStore(): Store<RootState>;
}
4.API 服务层 uc.ts --- 组织、错误处理、提示
要点解释
-
把"请求逻辑"封装到 service 层好处:当后端 API 改动或要加鉴权、拦截器,只修改这里。
-
JavaApiHandle看起来是项目封装的请求封装(axios 封装)。通常该封装会处理 baseURL、请求/响应拦截器、错误统一处理、自动加 token 等。
推荐的改进(错误处理 + 返回值)
javascript
export async function getVerifyCode(opts) {
try {
const res = await JavaApiHandle.post({ url: '/payslip-api/mobile/send', data: {...} })
showNotify({ type: 'success', message: `验证码已发送至${opts.dest}` })
return res
} catch (err) {
showNotify({ type: 'danger', message: '发送失败,请重试' })
throw err // 让调用方也能捕获
}
}
统一请求封装的常见做法
-
设置
Authorizationheader(从 store 或 localStorage 读取 token) -
对 401 做统一处理(自动跳转登录或刷新 token)
-
抛出标准化错误给上层显示