1. Vue工程环境搭建全指南
作为前端开发的主流框架之一,Vue以其简洁的API和渐进式特性深受开发者喜爱。要充分发挥Vue的优势,首先需要正确配置开发环境。这里我将分享从零开始搭建Vue项目的完整流程,以及如何利用Vue的核心特性——响应式函数。
1.1 开发环境准备
在开始创建Vue项目前,需要确保本地已安装Node.js环境(建议版本16.x以上)。打开终端运行以下命令检查版本:
bash复制node -v
npm -v
如果没有安装,可以从Node.js官网下载LTS版本。安装完成后,建议配置npm镜像源以加速依赖下载:
bash复制npm config set registry https://registry.npmmirror.com
1.2 Vue CLI与Vite的选择
目前主流的Vue项目脚手架有两种选择:
- Vue CLI:官方传统脚手架,适合需要完整Webpack配置的项目
- Vite:新一代构建工具,启动速度和热更新更快
对于新项目,我推荐使用Vite。安装Vue项目创建工具:
bash复制npm install -g @vue/cli
npm install -g create-vite
2. 创建Vue项目实战
2.1 使用Vite初始化项目
在目标目录下执行:
bash复制npm create vite@latest my-vue-app --template vue
这会在当前目录创建名为my-vue-app的Vue3项目。进入项目目录并安装依赖:
bash复制cd my-vue-app
npm install
项目结构说明:
src/:核心开发目录main.js:应用入口文件App.vue:根组件
public/:静态资源vite.config.js:Vite配置文件
2.2 项目启动与配置
启动开发服务器:
bash复制npm run dev
默认会在http://localhost:5173启动服务。如果需要修改端口,可以在vite.config.js中配置:
javascript复制export default defineConfig({
server: {
port: 3000
}
})
3. Vue响应式系统深度解析
3.1 响应式基础
Vue3使用Proxy实现了更强大的响应式系统。在选项式API中,data()函数返回的对象会自动成为响应式数据:
javascript复制export default {
data() {
return {
count: 0
}
}
}
在组合式API中,需要使用ref或reactive显式声明响应式数据:
javascript复制import { ref, reactive } from 'vue'
const count = ref(0)
const state = reactive({
message: 'Hello Vue!'
})
3.2 ref与reactive的差异
| 特性 | ref | reactive |
|---|---|---|
| 数据类型 | 基本类型/对象 | 仅对象 |
| 访问方式 | .value | 直接访问 |
| 模板使用 | 自动解包 | 直接使用 |
| 替换整个值 | 支持 | 不支持 |
实际开发中的选择建议:
- 单个基本类型值使用
ref - 相关联的一组数据使用
reactive - 表单数据推荐使用
reactive
3.3 计算属性与监听器
计算属性computed用于派生状态:
javascript复制import { computed } from 'vue'
const doubleCount = computed(() => count.value * 2)
监听器watch用于执行副作用:
javascript复制import { watch } from 'vue'
watch(count, (newVal, oldVal) => {
console.log(`count变化: ${oldVal} -> ${newVal}`)
}, { immediate: true })
4. 常见问题与解决方案
4.1 响应式丢失问题
问题现象:修改数据后视图不更新
常见原因:
- 直接解构reactive对象
- 直接替换reactive对象
- 在异步回调中操作数据
解决方案:
- 使用
toRefs保持解构后的响应性 - 修改reactive对象的属性而非整个对象
- 在异步操作中使用
nextTick
4.2 性能优化技巧
- 对大列表使用
v-for时始终指定key - 避免在模板中使用复杂表达式,改用计算属性
- 使用
shallowRef或shallowReactive减少不必要的响应式开销 - 合理使用
watchEffect和watch的flush选项
5. 工程化实践建议
5.1 目录结构优化
推荐的项目结构:
code复制src/
├── assets/ # 静态资源
├── components/ # 公共组件
├── composables/ # 组合式函数
├── router/ # 路由配置
├── stores/ # 状态管理
├── utils/ # 工具函数
├── views/ # 页面组件
├── App.vue # 根组件
└── main.js # 入口文件
5.2 代码规范配置
建议配置ESLint保证代码质量:
bash复制npm install eslint eslint-plugin-vue --save-dev
示例.eslintrc.js配置:
javascript复制module.exports = {
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended'
],
rules: {
'vue/multi-word-component-names': 'off'
}
}
5.3 状态管理选择
对于复杂应用,推荐使用Pinia替代Vuex:
bash复制npm install pinia
基本使用示例:
javascript复制// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++
}
}
})
在组件中使用:
javascript复制import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
counter.increment()
6. 响应式原理进阶
6.1 响应式实现原理
Vue3的响应式系统基于Proxy实现,核心流程:
- 通过
reactive()创建响应式代理 - 访问属性时收集依赖(track)
- 修改属性时触发更新(trigger)
简易实现示例:
javascript复制function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
track(target, key)
return target[key]
},
set(target, key, value) {
target[key] = value
trigger(target, key)
return true
}
})
}
6.2 自定义响应式工具
可以基于Vue响应式API封装实用工具函数:
javascript复制import { ref, watch } from 'vue'
export function useStorage(key, defaultValue) {
const data = ref(JSON.parse(localStorage.getItem(key)) || defaultValue)
watch(data, (newVal) => {
localStorage.setItem(key, JSON.stringify(newVal))
}, { deep: true })
return data
}
使用示例:
javascript复制const settings = useStorage('app-settings', { theme: 'light' })
settings.value.theme = 'dark' // 会自动同步到localStorage
7. 测试与调试
7.1 组件单元测试
推荐使用Vitest进行测试:
bash复制npm install -D vitest @vue/test-utils
测试示例:
javascript复制import { mount } from '@vue/test-utils'
import Counter from './Counter.vue'
test('increments counter', async () => {
const wrapper = mount(Counter)
await wrapper.find('button').trigger('click')
expect(wrapper.find('span').text()).toBe('1')
})
7.2 调试技巧
- 使用Vue Devtools检查组件层次和状态
- 在模板中使用
{{ $props }}检查传入的props - 使用
debugger语句配合浏览器开发者工具 - 通过
v-once定位不必要的重新渲染
8. 项目构建与部署
8.1 生产环境构建
bash复制npm run build
构建产物默认输出到dist/目录。可以通过配置修改输出:
javascript复制// vite.config.js
export default defineConfig({
build: {
outDir: 'output',
assetsDir: 'static'
}
})
8.2 部署优化建议
- 配置正确的静态资源路径:
javascript复制// vite.config.js
export default defineConfig({
base: process.env.NODE_ENV === 'production' ? '/your-subpath/' : '/'
})
- 启用gzip压缩:
bash复制npm install vite-plugin-compression --save-dev
- 配置路由history模式的后端支持
9. 响应式最佳实践
在实际项目中,我总结了以下经验:
- 状态组织:按照业务模块而非技术类型组织状态
- 组件设计:保持组件单一职责,合理划分状态所有权
- 性能敏感:在大型列表中使用虚拟滚动(如vue-virtual-scroller)
- 类型安全:配合TypeScript使用,增强代码可靠性
- 状态共享:简单场景使用provide/inject,复杂场景使用Pinia
一个典型的组合式函数示例:
javascript复制// composables/useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
在组件中使用:
javascript复制import { useMouse } from './composables/useMouse'
const { x, y } = useMouse()
10. 生态集成
10.1 UI组件库集成
推荐使用Element Plus或Ant Design Vue:
bash复制npm install element-plus
全局注册:
javascript复制// main.js
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
createApp(App)
.use(ElementPlus)
.mount('#app')
10.2 路由配置
使用Vue Router:
bash复制npm install vue-router
基本配置:
javascript复制// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: () => import('../views/About.vue') }
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
10.3 国际化方案
使用vue-i18n:
bash复制npm install vue-i18n
配置示例:
javascript复制// i18n.js
import { createI18n } from 'vue-i18n'
const messages = {
en: {
greeting: 'Hello!'
},
zh: {
greeting: '你好!'
}
}
const i18n = createI18n({
locale: 'zh',
messages
})
export default i18n
在模板中使用:
html复制<p>{{ $t('greeting') }}</p>
11. 项目优化进阶
11.1 代码分割
利用动态导入实现路由级和组件级代码分割:
javascript复制const UserDetails = () => import('./views/UserDetails.vue')
11.2 异步组件优化
配合Suspense使用:
html复制<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>Loading...</div>
</template>
</Suspense>
11.3 性能监控
集成web-vitals监控核心性能指标:
bash复制npm install web-vitals
使用示例:
javascript复制import { getCLS, getFID, getLCP } from 'web-vitals'
getCLS(console.log)
getFID(console.log)
getLCP(console.log)
12. 样式管理方案
12.1 CSS预处理器
安装Sass:
bash复制npm install -D sass
在组件中使用:
html复制<style lang="scss">
$primary-color: #42b983;
.text {
color: $primary-color;
}
</style>
12.2 CSS Modules
启用CSS Modules:
javascript复制// vite.config.js
export default defineConfig({
css: {
modules: {
localsConvention: 'camelCase'
}
}
})
使用示例:
html复制<template>
<p :class="$style.hello">Hello</p>
</template>
<style module>
.hello {
color: red;
}
</style>
12.3 原子化CSS
推荐使用UnoCSS:
bash复制npm install -D unocss @unocss/reset
配置:
javascript复制// vite.config.js
import Unocss from 'unocss/vite'
export default defineConfig({
plugins: [Unocss()]
})
13. 服务端渲染方案
13.1 Nuxt.js简介
Nuxt.js是基于Vue的SSR框架:
bash复制npx nuxi init my-nuxt-app
13.2 静态站点生成
使用VitePress创建文档站点:
bash复制npm install -D vitepress
14. 移动端开发
14.1 响应式适配方案
使用postcss-pxtorem自动转换px为rem:
bash复制npm install -D postcss postcss-pxtorem
配置:
javascript复制// postcss.config.js
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 16,
propList: ['*']
}
}
}
14.2 手势库集成
使用@vueuse/gesture处理触摸交互:
bash复制npm install @vueuse/gesture
使用示例:
javascript复制import { useGesture } from '@vueuse/gesture'
const bind = useGesture({
onDrag: ({ active, movement: [mx, my] }) => {
// 处理拖拽逻辑
}
})
15. 微前端集成
15.1 使用qiankun
主应用配置:
javascript复制import { registerMicroApps, start } from 'qiankun'
registerMicroApps([
{
name: 'vue-subapp',
entry: '//localhost:7101',
container: '#subapp-container',
activeRule: '/subapp'
}
])
start()
子应用配置:
javascript复制// main.js
import { createApp } from 'vue'
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
let app
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
createApp(App).mount('#app')
} else {
renderWithQiankun({
mount(props) {
app = createApp(App)
app.mount(props.container.querySelector('#app'))
},
unmount() {
app.unmount()
}
})
}
16. 安全实践
16.1 XSS防护
- 使用
v-html时要确保内容可信 - 对用户输入进行转义处理
- 设置Content Security Policy
16.2 CSRF防护
- 确保API请求携带CSRF Token
- 设置SameSite Cookie属性
- 验证Origin和Referer头部
17. 错误处理
17.1 全局错误处理
javascript复制// main.js
app.config.errorHandler = (err, vm, info) => {
console.error('全局错误:', err)
// 上报错误到监控系统
}
17.2 异步错误捕获
使用errorCaptured生命周期钩子:
javascript复制export default {
errorCaptured(err, vm, info) {
// 处理组件树中冒泡上来的错误
return false // 阻止错误继续向上传播
}
}
18. 动画与过渡
18.1 基本过渡效果
html复制<transition name="fade">
<div v-if="show">内容</div>
</transition>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
18.2 动画库集成
使用GSAP实现复杂动画:
bash复制npm install gsap
使用示例:
javascript复制import { gsap } from 'gsap'
onMounted(() => {
gsap.to('.box', {
x: 100,
duration: 1,
ease: 'power2.out'
})
})
19. 服务Worker与PWA
19.1 创建PWA应用
bash复制npm install -D vite-plugin-pwa
配置:
javascript复制// vite.config.js
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
plugins: [
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'My Vue App',
short_name: 'VueApp',
theme_color: '#ffffff'
}
})
]
})
20. Web Components集成
20.1 将Vue组件导出为Web Components
javascript复制// main.js
import { defineCustomElement } from 'vue'
const MyElement = defineCustomElement({
props: ['title'],
template: `<div>{{ title }}</div>`
})
customElements.define('my-element', MyElement)
20.2 在Vue中使用Web Components
javascript复制// vite.config.js
export default defineConfig({
optimizeDeps: {
include: ['@webcomponents/webcomponentsjs']
}
})
在模板中直接使用:
html复制<my-element title="Hello"></my-element>
21. 可视化与图表
21.1 ECharts集成
bash复制npm install echarts vue-echarts
使用示例:
javascript复制import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart } from 'echarts/charts'
import {
TitleComponent,
TooltipComponent,
LegendComponent
} from 'echarts/components'
import VChart from 'vue-echarts'
use([
CanvasRenderer,
PieChart,
TitleComponent,
TooltipComponent,
LegendComponent
])
// 在组件中注册
components: { VChart }
22. 测试驱动开发
22.1 组件测试实践
javascript复制import { mount } from '@vue/test-utils'
import Counter from './Counter.vue'
describe('Counter', () => {
it('点击按钮增加计数', async () => {
const wrapper = mount(Counter)
expect(wrapper.find('span').text()).toBe('0')
await wrapper.find('button').trigger('click')
expect(wrapper.find('span').text()).toBe('1')
})
})
22.2 E2E测试
使用Cypress:
bash复制npm install -D cypress
测试示例:
javascript复制describe('首页测试', () => {
it('成功加载', () => {
cy.visit('/')
cy.contains('h1', 'Welcome')
})
})
23. 性能分析
23.1 Lighthouse审计
bash复制npm install -D lighthouse
运行审计:
bash复制npx lighthouse http://localhost:5173 --view
23.2 性能监控
使用web-vitals:
javascript复制import { getLCP, getFID, getCLS } from 'web-vitals'
getLCP(console.log)
getFID(console.log)
getCLS(console.log)
24. 部署策略
24.1 静态托管
推荐平台:
- Vercel
- Netlify
- GitHub Pages
24.2 Docker部署
示例Dockerfile:
dockerfile复制FROM node:16 as builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
25. 持续集成
25.1 GitHub Actions配置
示例workflow:
yaml复制name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
- run: npm install
- run: npm run build
- run: npm run test
26. 项目文档
26.1 组件文档生成
使用Storybook:
bash复制npx storybook init
26.2 API文档
使用TypeDoc:
bash复制npm install -D typedoc
配置:
json复制// typedoc.json
{
"entryPoints": ["src/main.ts"],
"out": "docs"
}
27. 团队协作
27.1 Git工作流
推荐Git Flow:
main分支用于生产环境develop分支用于集成开发- 功能分支基于
develop创建 - 发布分支从
develop创建
27.2 代码审查
配置Husky实现提交前检查:
bash复制npm install -D husky lint-staged
配置:
json复制// package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,vue}": ["eslint --fix", "prettier --write"]
}
}
28. 项目升级
28.1 Vue2到Vue3迁移
主要变更点:
- 组合式API替代选项式API
- 片段支持(多根节点组件)
- v-model变更
- 事件API变更
- 过渡类名变更
28.2 迁移工具
使用官方迁移构建版本:
javascript复制import { createApp } from 'vue-demi'
29. 高级响应式模式
29.1 状态机模式
使用XState管理复杂状态:
bash复制npm install xstate @xstate/vue
示例:
javascript复制import { createMachine } from 'xstate'
import { useMachine } from '@xstate/vue'
const toggleMachine = createMachine({
id: 'toggle',
initial: 'inactive',
states: {
inactive: { on: { TOGGLE: 'active' } },
active: { on: { TOGGLE: 'inactive' } }
}
})
const { state, send } = useMachine(toggleMachine)
29.2 不可变数据
使用Immer处理不可变数据:
bash复制npm install immer
示例:
javascript复制import produce from 'immer'
const nextState = produce(baseState, draft => {
draft[1].done = true
draft.push({ title: '新项' })
})
30. 项目模板推荐
30.1 企业级模板
推荐vue-vben-admin:
- 基于Vue3 + TypeScript
- 完整的前后端解决方案
- 丰富的业务组件
30.2 移动端模板
推荐vant-template:
- 基于Vant UI
- 预设常用移动端配置
- 集成rem适配方案
31. 调试技巧进阶
31.1 自定义指令调试
创建调试指令:
javascript复制app.directive('debug', {
mounted(el, binding) {
console.log('指令绑定:', binding)
}
})
使用:
html复制<div v-debug="{ value: data }"></div>
31.2 性能标记
使用performance.mark:
javascript复制import { onMounted } from 'vue'
onMounted(() => {
performance.mark('component-mounted')
// 后续可以在Performance面板查看时间线
})
32. 服务端通信
32.1 Axios封装
javascript复制// utils/request.js
import axios from 'axios'
const service = axios.create({
baseURL: import.meta.env.VITE_API_URL,
timeout: 5000
})
// 请求拦截器
service.interceptors.request.use(config => {
// 添加token等
return config
})
// 响应拦截器
service.interceptors.response.use(
response => response.data,
error => {
// 统一错误处理
return Promise.reject(error)
}
)
export default service
32.2 GraphQL集成
使用@vue/apollo-composable:
bash复制npm install @vue/apollo-composable @apollo/client graphql
配置:
javascript复制// main.js
import { ApolloClient, InMemoryCache } from '@apollo/client/core'
import { DefaultApolloClient } from '@vue/apollo-composable'
const apolloClient = new ApolloClient({
uri: 'https://api.graphqlplaceholder.com',
cache: new InMemoryCache()
})
app.provide(DefaultApolloClient, apolloClient)
33. 本地存储方案
33.1 本地存储封装
javascript复制// utils/storage.js
export const getItem = (key) => {
const value = localStorage.getItem(key)
try {
return JSON.parse(value)
} catch {
return value
}
}
export const setItem = (key, value) => {
localStorage.setItem(key, JSON.stringify(value))
}
export const removeItem = (key) => {
localStorage.removeItem(key)
}
33.2 加密存储
使用crypto-js:
bash复制npm install crypto-js
加密实现:
javascript复制import CryptoJS from 'crypto-js'
const SECRET_KEY = 'your-secret-key'
export const encrypt = (data) => {
return CryptoJS.AES.encrypt(JSON.stringify(data), SECRET_KEY).toString()
}
export const decrypt = (ciphertext) => {
const bytes = CryptoJS.AES.decrypt(ciphertext, SECRET_KEY)
return JSON.parse(bytes.toString(CryptoJS.enc.Utf8))
}
34. 权限控制方案
34.1 路由权限控制
javascript复制// router/index.js
router.beforeEach((to, from, next) => {
const hasToken = localStorage.getItem('token')
if (to.meta.requiresAuth && !hasToken) {
next('/login')
} else {
next()
}
})
34.2 组件级权限
自定义指令实现:
javascript复制app.directive('permission', {
mounted(el, binding) {
const { value } = binding
const permissions = store.state.user.permissions
if (!permissions.includes(value)) {
el.parentNode?.removeChild(el)
}
}
})
使用:
html复制<button v-permission="'user:create'">创建用户</button>
35. 多环境配置
35.1 环境变量管理
.env文件示例:
code复制VITE_API_URL=https://api.example.com
VITE_DEBUG=true
使用:
javascript复制console.log(import.meta.env.VITE_API_URL)
35.2 环境特定配置
javascript复制// config.js
const envConfigs = {
development: {
apiBase: 'http://localhost:3000'
},
production: {
apiBase: 'https://api.example.com'
}
}
export default envConfigs[import.meta.env.MODE] || envConfigs.production
36. 错误监控
36.1 Sentry集成
bash复制npm install @sentry/vue @sentry/tracing
配置:
javascript复制import * as Sentry from '@sentry/vue'
import { Integrations } from '@sentry/tracing'
Sentry.init({
app,
dsn: 'your-dsn',
integrations: [
new Integrations.BrowserTracing({
routingInstrumentation: Sentry.vueRouterInstrumentation(router)
})
],
tracesSampleRate: 1.0
})
36.2 性能监控
javascript复制import { init } from '@sentry/vue'
init({
app,
tracesSampleRate: 1.0,
integrations: [
new Sentry.Replay()
]
})
37. 代码分割策略
37.1 路由级分割
javascript复制const routes = [
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue')
}
]
37.2 组件级分割
javascript复制const AsyncComponent = defineAsyncComponent(() =>
import('./components/HeavyComponent.vue')
)
38. 构建优化
38.1 依赖分析
使用rollup-plugin-visualizer:
bash复制npm install -D rollup-plugin-visualizer
配置:
javascript复制// vite.config.js
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
visualizer()
]
})
38.2 分包策略
javascript复制// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor'
}
}
}
}
}
})
39. 服务端通信优化
39.1 请求取消
javascript复制const controller = new AbortController()
axios.get('/api/data', {
signal: controller.signal
})
// 取消请求
controller.abort()
39.2 请求重试
javascript复制import axiosRetry from 'axios-retry'
axiosRetry(axios, {
retries: 3,
retryDelay: axiosRetry.exponentialDelay
})
40. 项目重构技巧
40.1 组件拆分原则
- 单一职责原则
- 高内聚低耦合
- 合理控制组件规模
- 按功能而非技术划分
40.2 组合式函数提取
将可复用逻辑提取为组合式函数:
javascript复制// composables/usePagination.js
import { ref, computed } from 'vue'
export function usePagination(totalItems, itemsPerPage = 10) {
const currentPage = ref(1)
const totalPages = computed(() =>
Math.ceil(totalItems.value / itemsPerPage)
)
function nextPage() {
if (currentPage.value < totalPages.value) {
currentPage.value++
}
}
return { currentPage, totalPages, nextPage }
}
41. 设计模式应用
41.1 观察者模式
使用Vue的响应式系统:
javascript复制const observers = ref([])
function subscribe(callback) {
observers.value.push(callback)
}
function notify(data) {
observers.value.forEach(cb => cb(data))
}
41.2 策略模式
javascript复制const strategies = {
add: (a, b) => a + b,
subtract: (a, b) => a - b
}
function calculate(strategy, a, b) {
return strategies[strategy](a, b)
}
42. 性能监控
42.1 关键指标采集
javascript复制import { getCLS, getFID, getLCP } from 'web-vitals'
function sendToAnalytics(metric) {
console.log(metric)
}
getCLS(sendToAnalytics)
getFID(sendToAnalytics)
getLCP(sendToAnalytics)
42.2 内存监控
javascript复制setInterval(() => {
const memory = performance.memory
console.log(`内存使用: ${memory.usedJSHeapSize / 1024 / 1024} MB`)
}, 10000)
43. 无障碍访问
43.1 ARIA属性
html复制<button
aria-label="关闭"
aria-expanded="false"
@click="toggle"
>
<span aria-hidden="true">×</span>
</button>
43.2 键盘导航
javascript复制function handleKeyDown(e) {
switch(e.key) {
case 'ArrowDown':
// 处理向下键
break
case 'Enter':
// 处理回车键
break
}
}
44. 国际化进阶
44.1 动态语言切换
javascript复制const locale = ref('zh')
const messages = {
zh: { welcome: '欢迎' },
en: { welcome: 'Welcome' }
}
function t(key) {
return messages[locale.value][key]
}
44.2 复数处理
javascript复制function pluralize(key, count) {
const rules = {
en: {
apple: count === 1 ? 'apple' : 'apples'
}
}
return rules[locale.value][key]
}
45. 测试覆盖率
45.1 覆盖率统计
bash复制npm install -D c8
配置:
json复制{
"scripts": {
"test:coverage": "c8 vue-cli-service test:unit"
}
}
45.2 覆盖率阈值
json复制{
"c8": {
"check-coverage": true,
"branches": 80,
"lines": 80,
"functions": 80,
"statements": 80
}
}
46. 微交互优化
46.1 加载状态
javascript复制const isLoading = ref(false)
async function fetchData() {
isLoading.value = true
try {
await api.getData()
} finally {
isLoading.value = false
}
}
46.2 视觉反馈
html复制<button @click="submit" :class="{ 'shake': isError }">
提交
</button>
<style>
.shake {
animation: shake 0.5s;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
</style>
47. 移动端适配
47.1 1px边框解决方案
css复制.border-1px {
position: relative;
}
.border-1px::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background: #ddd;
transform: scaleY(0.5);
}
47.2 禁止长按菜单
css复制* {
-webkit