1. 项目概述:JavaWeb与AI技术融合的前端开发实践
这个项目源自黑马程序员JavaWeb课程体系的升级版本,特别融入了AI技术辅助开发的新趋势。作为一套完整的Web全栈开发解决方案,它聚焦于Vue3+ElementPlus的前端技术栈,同时整合了JavaWeb后端技术体系。在当前AI技术爆发的背景下,这种组合能够帮助开发者快速构建现代化、智能化的Web应用。
我最近在实际项目中完整实践了这套技术方案,发现Vue3的组合式API配合ElementPlus组件库,确实能大幅提升开发效率。特别是在处理复杂业务逻辑时,TypeScript的类型系统加上Vue3的响应式机制,让代码的可维护性显著提高。而AI技术的引入,则为代码生成、错误调试和性能优化提供了全新思路。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术栈深度解析
2.1 Vue3核心特性实战应用
Vue3相较于Vue2的改进不仅仅是性能提升,更带来了开发范式的转变。组合式API(Composition API)是最大的亮点,它解决了Options API在复杂组件中的代码组织问题。在实际项目中,我通常会这样组织代码:
typescript复制<script setup lang="ts">
// 响应式状态
const count = ref(0)
const doubled = computed(() => count.value * 2)
// 方法
function increment() {
count.value++
}
// 生命周期
onMounted(() => {
console.log('组件已挂载')
})
</script>
这种写法让相关逻辑可以集中在一起,而不是像Options API那样分散在data、methods等不同区块。对于大型项目,还可以使用<script setup>的语法糖进一步简化代码。
提示:Vue3的响应式系统基于Proxy实现,这意味着它能够检测到更多类型的变化,包括数组索引修改和对象属性添加。但在处理大型数组时需要注意性能问题。
2.2 ElementPlus组件库最佳实践
ElementPlus作为Vue3的UI组件库,提供了丰富的企业级组件。在实际使用中,我发现以下几个技巧特别实用:
- 表单验证的进阶用法:
typescript复制const formRules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 6, max: 16, message: '长度在6到16个字符', trigger: 'blur' }
],
password: [
{ validator: (rule, value, callback) => {
if (!/^(?=.*[a-z])(?=.*[A-Z]).+$/.test(value)) {
callback(new Error('必须包含大小写字母'))
} else {
callback()
}
}, trigger: 'blur' }
]
}
- 表格性能优化:
对于大数据量表格,一定要使用虚拟滚动:
html复制<el-table
:data="tableData"
height="500"
v-loading="loading"
row-key="id"
:tree-props="{children: 'children'}"
>
<!-- 列定义 -->
</el-table>
- 主题定制技巧:
在variables.scss中覆盖默认变量:
scss复制$--color-primary: #1890ff;
$--font-path: '~element-plus/theme-chalk/fonts';
@import "~element-plus/theme-chalk/src/index";
3. JavaWeb与Vue3前后端协作方案
3.1 接口对接规范设计
前后端分离架构中,接口规范至关重要。我们团队采用以下方案:
- 统一响应格式:
java复制public class Result<T> {
private Integer code; // 状态码
private String msg; // 消息
private T data; // 数据
// 成功静态方法
public static <T> Result<T> success(T data) {
return new Result<>(200, "成功", data);
}
// 失败静态方法
public static <T> Result<T> error(Integer code, String msg) {
return new Result<>(code, msg, null);
}
}
- Axios封装示例:
typescript复制const service = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 5000
})
// 请求拦截器
service.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
})
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data
if (res.code !== 200) {
ElMessage.error(res.msg || 'Error')
return Promise.reject(new Error(res.msg || 'Error'))
} else {
return res
}
},
error => {
ElMessage.error(error.message)
return Promise.reject(error)
}
)
3.2 权限控制实现方案
基于RBAC模型的权限控制是企业管理系统的核心需求。我们的实现方案包含以下关键点:
- 后端权限校验:
java复制@PreAuthorize("hasAuthority('system:user:list')")
@GetMapping("/list")
public Result<List<User>> listUsers() {
// 业务逻辑
}
- 前端动态路由:
typescript复制// 过滤异步路由
function filterAsyncRoutes(routes: RouteRecordRaw[], roles: string[]) {
const res: RouteRecordRaw[] = []
routes.forEach(route => {
const tmp = { ...route }
if (hasPermission(roles, tmp)) {
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles)
}
res.push(tmp)
}
})
return res
}
- 按钮级权限控制:
vue复制<template>
<el-button
v-if="hasPermission('system:user:add')"
type="primary"
@click="handleAdd"
>
新增用户
</el-button>
</template>
<script setup>
import { usePermission } from '@/hooks/usePermission'
const { hasPermission } = usePermission()
</script>
4. AI技术在Web开发中的创新应用
4.1 AI辅助代码生成实践
现代AI工具如GitHub Copilot已经能显著提升开发效率。在实际项目中,我总结了以下使用技巧:
- 组件生成提示词:
code复制/*
生成一个Vue3的表格组件,要求:
- 使用ElementPlus的el-table
- 支持分页和排序
- 包含状态筛选功能
- 使用TypeScript
- 导出为默认组件
*/
- API接口代码自动补全:
当输入axios.时,AI可以自动补全完整的请求代码:
typescript复制axios.get('/api/user/list', {
params: {
page: 1,
size: 10,
name: ''
}
}).then(response => {
// 处理响应
})
- 错误诊断辅助:
当遇到Vue警告时,可以直接将错误信息粘贴给AI工具,通常能获得准确的解决方案。
4.2 智能UI设计建议
AI工具如Figma AI插件可以根据需求描述生成初步的UI设计方案。我们的工作流程是:
- 用自然语言描述组件需求
- AI生成多个设计变体
- 人工选择最合适的方案进行调整
- 导出为Vue组件代码
例如描述:"需要一个用户资料卡片,包含头像、姓名、职位和社交图标,风格现代化,使用蓝色主色调"
5. 性能优化与调试技巧
5.1 Vue3应用性能调优
- 组件懒加载:
typescript复制const UserManagement = defineAsyncComponent(() =>
import('./views/UserManagement.vue')
)
- 状态管理优化:
对于大型应用,推荐使用Pinia并遵循以下原则:
- 按功能模块拆分store
- 避免在store中存储组件状态
- 使用getter缓存计算结果
- 渲染性能监控:
typescript复制import { getCurrentInstance } from 'vue'
const instance = getCurrentInstance()
const start = performance.now()
instance?.proxy?.$nextTick(() => {
const duration = performance.now() - start
if (duration > 50) {
console.warn(`渲染耗时 ${duration.toFixed(2)}ms`)
}
})
5.2 常见问题排查指南
- 响应式失效问题:
typescript复制// 错误做法
const state = reactive({})
state = newObject // 失去响应性
// 正确做法
Object.assign(state, newObject)
- ElementPlus样式覆盖无效:
确保样式文件引入顺序正确:
scss复制// 先引入变量文件
@use "~element-plus/theme-chalk/src/mixins/mixins" as *;
@use "~element-plus/theme-chalk/src/mixins/function" as *;
// 然后覆盖变量
$--color-primary: #1890ff;
// 最后引入主样式文件
@use "~element-plus/theme-chalk/src/index" as *;
- TypeScript类型推断问题:
为ElementPlus组件添加类型:
typescript复制import type { ElTable } from 'element-plus'
const tableRef = ref<InstanceType<typeof ElTable>>()
6. 项目架构设计与工程化实践
6.1 现代化项目目录结构
经过多个项目实践,我总结出以下高效目录结构:
code复制src/
├── api/ # API请求封装
├── assets/ # 静态资源
├── components/ # 公共组件
│ ├── business/ # 业务组件
│ └── base/ # 基础UI组件
├── composables/ # 组合式函数
├── router/ # 路由配置
├── store/ # 状态管理
├── styles/ # 全局样式
├── utils/ # 工具函数
├── views/ # 页面组件
├── App.vue # 根组件
└── main.ts # 应用入口
6.2 CI/CD自动化部署
对于JavaWeb+Vue3的全栈项目,推荐以下部署流程:
- 前端构建配置:
bash复制# 安装依赖
npm install
# 开发环境
npm run dev
# 生产构建
npm run build
# 预览生产版本
npm run preview
- Docker化部署:
dockerfile复制# 前端Dockerfile
FROM nginx:alpine
COPY dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
- Nginx配置优化:
nginx复制server {
listen 80;
server_name yourdomain.com;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
}
location /api/ {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
}
}
7. 进阶开发技巧与模式
7.1 高阶组件设计模式
- 渲染委托模式:
vue复制<!-- SmartList.vue -->
<template>
<el-table :data="items">
<template v-for="col in columns" :key="col.prop">
<el-table-column v-bind="col">
<template #default="scope">
<slot :name="`col-${col.prop}`" v-bind="scope"></slot>
</template>
</el-table-column>
</template>
</el-table>
</template>
<!-- 使用方式 -->
<SmartList :items="users" :columns="columns">
<template #col-name="{ row }">
<el-tag>{{ row.name }}</el-tag>
</template>
</SmartList>
- 组合式函数抽象:
typescript复制// usePagination.ts
export function usePagination(loadFn: (params: any) => Promise<any>) {
const loading = ref(false)
const data = ref([])
const pagination = reactive({
page: 1,
size: 10,
total: 0
})
const loadData = async () => {
try {
loading.value = true
const res = await loadFn({
page: pagination.page,
size: pagination.size
})
data.value = res.list
pagination.total = res.total
} finally {
loading.value = false
}
}
return {
loading,
data,
pagination,
loadData
}
}
7.2 微前端集成方案
对于大型企业应用,可以考虑使用微前端架构。基于wujie的集成方案:
- 主应用配置:
typescript复制import { registerMicroApps, start } from 'wujie'
registerMicroApps([
{
name: 'sub-app',
entry: '//localhost:7100',
container: '#subapp-container',
activeRule: '/subapp'
}
])
start()
- 子应用适配:
javascript复制// 子应用入口文件
if (window.__POWERED_BY_WUJIE__) {
let instance
window.__WUJIE_MOUNT = () => {
instance = createApp(App).mount('#app')
}
window.__WUJIE_UNMOUNT = () => {
instance.unmount()
}
} else {
createApp(App).mount('#app')
}
8. 测试策略与质量保障
8.1 前端测试金字塔实践
- 单元测试示例(Vitest):
typescript复制import { render } from '@testing-library/vue'
import Button from '../Button.vue'
test('renders button with correct text', async () => {
const { getByText } = render(Button, {
props: {
text: 'Submit'
}
})
expect(getByText('Submit')).toBeTruthy()
})
- 组件测试技巧:
typescript复制import { mount } from '@vue/test-utils'
import Form from '../Form.vue'
test('form validation works', async () => {
const wrapper = mount(Form)
await wrapper.find('input').setValue('')
await wrapper.find('form').trigger('submit')
expect(wrapper.find('.error-message').text()).toBe('该字段为必填项')
})
- E2E测试(Cypress):
javascript复制describe('Login Flow', () => {
it('should login successfully', () => {
cy.visit('/login')
cy.get('#username').type('admin')
cy.get('#password').type('123456')
cy.get('button[type=submit]').click()
cy.url().should('include', '/dashboard')
})
})
8.2 性能监控方案
- Lighthouse CI集成:
yaml复制# .github/workflows/lighthouse.yml
name: Lighthouse Audit
on: [push]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- run: npm install && npm run build
- uses: treosh/lighthouse-ci-action@v8
with:
urls: |
http://localhost:4173/
budgetPath: ./lighthouse-budget.json
- 自定义性能指标收集:
typescript复制// 在应用入口收集性能指标
const perfMetrics = {
FCP: 0,
LCP: 0,
FID: 0
}
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name === 'first-contentful-paint') {
perfMetrics.FCP = entry.startTime
} else if (entry.name === 'largest-contentful-paint') {
perfMetrics.LCP = entry.startTime
}
}
})
observer.observe({ type: 'paint', buffered: true })
// 发送数据到监控系统
window.addEventListener('load', () => {
navigator.sendBeacon('/api/perf', perfMetrics)
})
9. 项目实战:用户管理系统案例
9.1 功能模块设计
完整实现一个用户管理系统需要以下核心模块:
- 用户认证模块:
- JWT登录/登出
- 密码加密存储
- 权限验证中间件
- 用户管理模块:
- CRUD操作
- 角色分配
- 状态管理
- 系统监控模块:
- 操作日志
- 性能监控
- 异常追踪
9.2 核心代码实现
- 后端Spring Boot控制器:
java复制@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
@PreAuthorize("hasAuthority('system:user:list')")
public Result<PageInfo<User>> listUsers(
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size,
UserQuery query) {
PageHelper.startPage(page, size);
List<User> users = userService.listUsers(query);
return Result.success(new PageInfo<>(users));
}
@PostMapping
@PreAuthorize("hasAuthority('system:user:add')")
public Result addUser(@Valid @RequestBody User user) {
return userService.addUser(user);
}
}
- 前端Vue3页面组件:
vue复制<template>
<div class="user-management">
<el-card>
<template #header>
<div class="flex justify-between">
<span>用户列表</span>
<el-button
type="primary"
@click="handleAdd"
v-permission="'system:user:add'"
>
新增用户
</el-button>
</div>
</template>
<el-table :data="tableData" v-loading="loading">
<el-table-column prop="username" label="用户名" />
<el-table-column prop="nickname" label="昵称" />
<el-table-column prop="status" label="状态">
<template #default="{row}">
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
{{ row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template #default="{row}">
<el-button size="small" @click="handleEdit(row)">编辑</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:currentPage="pagination.page"
v-model:page-size="pagination.size"
:total="pagination.total"
@current-change="loadData"
layout="total, sizes, prev, pager, next, jumper"
/>
</el-card>
<UserDialog
v-model="dialogVisible"
:current-user="currentUser"
@success="loadData"
/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { getUsers, deleteUser } from '@/api/user'
import UserDialog from './components/UserDialog.vue'
const loading = ref(false)
const tableData = ref([])
const pagination = reactive({
page: 1,
size: 10,
total: 0
})
const loadData = async () => {
try {
loading.value = true
const res = await getUsers({
page: pagination.page,
size: pagination.size
})
tableData.value = res.list
pagination.total = res.total
} finally {
loading.value = false
}
}
onMounted(loadData)
</script>
10. 开发环境配置与工具链
10.1 推荐开发工具组合
- IDE配置:
- VS Code + Volar扩展(Vue3官方推荐)
- ESLint + Prettier代码规范
- GitLens版本控制增强
- 浏览器插件:
- Vue Devtools 6.0+
- JSON Formatter
- Axios Debugger
- API测试工具:
- Postman或Insomnia
- Swagger UI自动生成
10.2 高效开发技巧
- 代码片段加速开发:
json复制// .vscode/vue.json
{
"Vue3 Component": {
"prefix": "vue3",
"body": [
"<template>",
" <div>",
" $1",
" </div>",
"</template>",
"",
"<script setup lang=\"ts\">",
"$2",
"</script>",
"",
"<style scoped>",
"$3",
"</style>"
]
}
}
- 调试技巧:
javascript复制// 在组合式API中调试
const debug = (value) => {
console.log(value)
return value
}
// 使用示例
const count = debug(ref(0))
- 性能分析工具:
bash复制# 生成性能分析报告
npx vite build --profile
11. 学习资源与进阶路径
11.1 官方文档精要
- Vue3文档重点章节:
- 响应式基础
- 组合式API详解
- 渲染机制与优化
- TypeScript集成
- ElementPlus必看内容:
- 表单验证规则
- 表格性能优化
- 主题定制方法
- 国际化实现
- Spring Boot关键特性:
- 自动配置原理
- 安全框架集成
- 数据访问层设计
- 异常处理机制
11.2 实战提升建议
- 项目迭代路线:
- 第一阶段:基础CRUD实现
- 第二阶段:权限系统集成
- 第三阶段:性能优化
- 第四阶段:微服务拆分
- 代码质量提升方法:
- 实施代码审查
- 引入静态分析工具
- 编写单元测试
- 持续集成实践
- 架构演进方向:
- 从单体到微前端
- 引入领域驱动设计
- 实现前后端分离部署
- 构建自动化监控体系
12. 团队协作与代码规范
12.1 Git工作流实践
- 分支策略:
code复制main - 生产环境代码
release/* - 预发布分支
develop - 集成测试分支
feature/* - 功能开发分支
hotfix/* - 紧急修复分支
- 提交信息规范:
code复制<type>(<scope>): <subject>
feat(user): 添加用户注册功能
fix(auth): 修复登录令牌过期问题
docs: 更新API接口文档
style: 调整代码格式
refactor: 重构用户服务层
test: 添加权限测试用例
chore: 更新依赖版本
- Code Review要点:
- 功能实现是否符合需求
- 代码结构是否清晰
- 是否有潜在性能问题
- 测试覆盖率是否足够
- 是否符合团队规范
12.2 前端代码规范
- 命名约定:
- 变量:camelCase
- 组件:PascalCase
- 常量:UPPER_CASE
- 接口:I前缀或Type后缀
- 枚举:E前缀
- Vue文件结构:
vue复制<template>
<!-- 模板内容 -->
</template>
<script setup lang="ts">
// 组合式API逻辑
</script>
<style scoped>
/* 组件样式 */
</style>
- TypeScript最佳实践:
- 避免使用any类型
- 为复杂数据结构定义接口
- 使用类型守卫缩小类型范围
- 合理使用泛型提高复用性
- 为工具函数添加完整类型定义
13. 项目部署与运维
13.1 生产环境部署方案
- 前端部署流程:
bash复制# 安装依赖
npm ci --production
# 构建生产版本
npm run build
# 静态资源部署
rsync -avz dist/ user@server:/var/www/html/
- Nginx优化配置:
nginx复制# 启用gzip压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, no-transform";
}
# 前端路由处理
location / {
try_files $uri $uri/ /index.html;
}
- CDN加速配置:
- 将静态资源上传至CDN
- 修改构建配置使用CDN地址
- 设置合理的缓存策略
13.2 监控与告警
- 前端监控指标:
- 页面加载性能
- API请求成功率
- 用户交互延迟
- 资源加载错误
- 控制台错误
- Sentry集成示例:
typescript复制import * as Sentry from '@sentry/vue'
app = createApp(App)
Sentry.init({
app,
dsn: 'your-dsn',
integrations: [
new Sentry.BrowserTracing({
routingInstrumentation: Sentry.vueRouterInstrumentation(router)
})
],
tracesSampleRate: 0.2
})
- 健康检查端点:
java复制@RestController
@RequestMapping("/actuator")
public class HealthController {
@GetMapping("/health")
public ResponseEntity<String> health() {
return ResponseEntity.ok("UP");
}
@GetMapping("/info")
public Map<String, String> info() {
return Map.of(
"app", "User Management System",
"version", "1.0.0"
);
}
}
14. 安全防护最佳实践
14.1 前端安全防护
- XSS防护措施:
- 使用DOMPurify处理富文本
- 设置Content Security Policy
- 避免使用v-html指令
- 对用户输入进行转义
- CSRF防护方案:
typescript复制// Axios配置
service.interceptors.request.use(config => {
config.headers['X-Requested-With'] = 'XMLHttpRequest'
const token = getCookie('XSRF-TOKEN')
if (token) {
config.headers['X-XSRF-TOKEN'] = token
}
return config
})
- 敏感数据处理:
typescript复制// 使用crypto-js加密敏感数据
import CryptoJS from 'crypto-js'
const encryptData = (data: string, key: string) => {
return CryptoJS.AES.encrypt(data, key).toString()
}
14.2 后端安全加固
- Spring Security配置:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
- SQL注入防护:
- 使用预编译语句
- 实施最小权限原则
- 定期更新数据库补丁
- 使用ORM框架的安全查询方法
- API安全增强:
- 实施速率限制
- 请求参数校验
- 敏感操作日志记录
- 定期更换密钥
15. 国际化与多主题实现
15.1 Vue3国际化方案
- i18n配置示例:
typescript复制import { createI18n } from 'vue-i18n'
const i18n = createI18n({
locale: localStorage.getItem('locale') || 'zh-CN',
messages: {
'zh-CN': {
user: {
name: '用户名',
login: '登录'
}
},
'en-US': {
user: {
name: 'Username',
login: 'Sign In'
}
}
}
})
app.use(i18n)
- ElementPlus国际化:
typescript复制import zhCn from 'element-plus/lib/locale/lang/zh-cn'
import en from 'element-plus/lib/locale/lang/en'
const locale = computed(() =>
i18n.global.locale.value === 'zh-CN' ? zhCn : en
)
app.use(ElementPlus, { locale })
- 动态切换语言:
vue复制<template>
<el-dropdown @command="changeLanguage">
<span class="el-dropdown-link">
{{ $t('language') }}<i class="el-icon-arrow-down"></i>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="zh-CN">中文</el-dropdown-item>
<el-dropdown-item command="en-US">English</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script setup>
const { locale } = useI18n()
const changeLanguage = (lang) => {
locale.value = lang
localStorage.setItem('locale', lang)
}
</script>
15.2 多主题切换实现
- CSS变量方案:
scss复制// variables.scss
:root {
--primary-color: #409EFF;
--success-color: #67C23A;
// 其他变量...
}
[data-theme="dark"] {
--primary-color: #3375b9;
--success-color: #5daf34;
// 暗色主题变量...
}
- 主题切换组件:
vue复制<template>
<el-switch
v-model="isDark"
active-text="暗色"
inactive-text="亮色"
@change="toggleTheme"
/>
</template>
<script setup>
const isDark = ref(localStorage.getItem('theme') === 'dark')
const toggleTheme = (val) => {
const theme = val ? 'dark' : 'light'
document.documentElement.setAttribute('data-theme', theme)
localStorage.setItem('theme', theme)
}
onMounted(() => {
const savedTheme = localStorage.getItem('theme') || 'light'
document.documentElement.setAttribute('data-theme', savedTheme)
isDark.value = savedTheme === 'dark'
})
</script>
- ElementPlus主题覆盖:
javascript复制// 动态修改ElementPlus主题色
const setPrimaryColor = (color) => {
document.documentElement.style.setProperty('--el-color-primary', color)
const theme = color === '#409EFF' ? 'light' : 'dark'
document.documentElement.setAttribute('data-theme', theme)
}
16. 移动端适配与响应式设计
16.1 响应式布局方案
- Flex+Grid布局系统:
scss复制.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.card {
display: flex;
flex-direction: column;
@media (max-width: 768px) {
flex-direction: row;
}
}
- ElementPlus响应式工具:
vue复制<template>
<el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<!-- 内容 -->
</el-col>
</el-row>
</template>
- 自定义Hook处理响应式:
typescript复制import { ref, onMounted, onUnmounted } from 'vue'
export function useBreakpoints() {
const width = ref(window.innerWidth)
const onResize = () => {
width.value = window.innerWidth
}
onMounted(() => {
window.addEventListener('resize', onResize)
})
onUnmounted(() => {
window.removeEventListener('resize', onResize)
})
const isMobile = computed(() => width.value < 768)
const isTablet = computed(() => width.value >= 768 && width.value < 992)
const isDesktop = computed(() => width.value >= 992)
return { isMobile, isTablet, isDesktop }
}
16.2 移动端专属优化
- 触摸事件处理:
vue复制<template>
<div
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>
<!-- 内容 -->
</div>
</template>
<script setup>
const handleTouchStart = (e) => {
// 记录触摸起始位置
}
const handleTouchMove = (e) => {
// 计算滑动方向
}
const handleTouchEnd = (e) => {
// 处理滑动结果
}
</script>
- 移动端表单优化:
html复制<input
type="text"
inputmode="numeric"
pattern="[0-9]*"
placeholder="请输入手机号"
>
- PWA集成:
javascript复制// vite.config.js
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
plugins: [
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: '用户管理系统',
short_name: 'UMS',
theme_color: '#ffffff',
icons: [
{
src: '/pwa-192x192.png',
sizes: '192x192',
type: 'image/png'
}
]
}
})
]
})
17. 状态管理进阶模式
17.1 Pinia状态管理实践
- 模块化Store设计:
typescript复制// stores/user.ts
export const useUserStore = defineStore('user', {
state: () => ({
token: localStorage.getItem('token') || '',
userInfo: null
}),
actions: {
async login(credentials) {
const res = await api.login(credentials)
this.token = res.token
this.userInfo = res.user
localStorage.setItem('token', res.token)
},
logout() {
this.token = ''
this.userInfo = null
localStorage.removeItem('token')
}
},
getters: {
isAuthenticated: (state) => !!state.token
}
})
- 持久化存储方案:
typescript复制// 安装pinia-plugin-persistedstate
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia
