Search K
Appearance
👍欢迎大家积极投稿交流👍
如果文档内容陈旧或者链接失效,请发现后及时同步,我将尽快修改
👇微信👇

Appearance
user-profile.vue、api-request.jsUserProfile.vue、TodoList.vueuserName、isLoadingMAX_COUNT、API_BASE_URLisVisible、hasPermissiongetUserInfo()、formatDate()"editor.tabSize": 2 和 "editor.insertSpaces": true 来保持一致const arr = [1, 2, 3]// 好的示例
const user = {
id: 1,
name: 'John',
email: 'john@example.com',
age: 25
}
// 数组换行示例
const fruits = [
'apple',
'banana',
'orange',
'grape'
]namecomponentspropsemitssetup 或 data、computed、watchmethods// 好的示例
const props = defineProps({
/**
* 用户信息对象
*/
userInfo: {
type: Object,
required: true
},
/**
* 是否显示加载状态
*/
loading: {
type: Boolean,
default: false
},
/**
* 分页大小
*/
pageSize: {
type: Number,
default: 10,
validator: (value) => value > 0
}
})// 好的示例
const emit = defineEmits({
/**
* 更新用户信息事件
* @param {Object} userInfo - 更新后的用户信息
*/
'update:userInfo': (userInfo) => typeof userInfo === 'object',
/**
* 点击事件
* @param {MouseEvent} event - 鼠标事件对象
*/
'click': (event) => event instanceof MouseEvent
}): 表示 v-bind,@ 表示 v-onv-if 和 v-for 时应注意优先级,避免同时使用<template>
<UserProfile
:user-info="userInfo"
:loading="loading"
@update:userInfo="handleUpdate"
@click="handleClick"
/>
</template><script setup> 语法糖简化组件编写ref 和 reactive 合理区分: computed 处理派生状态,避免在模板中进行复杂计算watch 和 watchEffect 监听数据变化,注意清理副作用use 开头命名scoped 修饰符避免样式污染:class 和 :style 绑定动态样式!important 覆盖样式ref:
.value 访问和修改值reactive:
.value// 好的示例
import { ref, reactive } from 'vue'
// 使用 ref 管理基本类型
const count = ref(0)
const loading = ref(false)
const message = ref('Hello')
// 使用 reactive 管理复杂对象
const user = reactive({
name: 'John',
age: 25,
address: {
city: 'Beijing',
district: 'Haidian'
}
})
// 修改值
count.value++
user.name = 'Tom'// 好的示例
import { ref, computed } from 'vue'
const items = ref([1, 2, 3, 4, 5])
/**
* 计算偶数的数量
*/
const evenCount = computed(() => {
return items.value.filter(item => item % 2 === 0).length
})
/**
* 计算总和
*/
const total = computed(() => {
return items.value.reduce((sum, item) => sum + item, 0)
})immediate 选项在初始时执行一次// 好的示例
import { ref, watch } from 'vue'
const searchQuery = ref('')
const searchResults = ref([])
// 监听搜索查询变化
watch(searchQuery, (newQuery, oldQuery) => {
// 清理函数
let timeoutId
if (newQuery) {
timeoutId = setTimeout(() => {
// 模拟异步搜索
searchApi(newQuery).then(results => {
searchResults.value = results
})
}, 300)
} else {
searchResults.value = []
}
// 返回清理函数
return () => {
if (timeoutId) clearTimeout(timeoutId)
}
})
// 深度监听对象变化
const user = ref({
name: 'John',
address: {
city: 'Beijing'
}
})
watch(
user,
(newUser) => {
console.log('User changed:', newUser)
},
{ deep: true }
)// 好的示例
import { ref, watchEffect } from 'vue'
const width = ref(0)
const height = ref(0)
// 监听窗口大小变化
watchEffect(() => {
const handleResize = () => {
width.value = window.innerWidth
height.value = window.innerHeight
}
window.addEventListener('resize', handleResize)
handleResize() // 立即执行一次
// 返回清理函数
return () => {
window.removeEventListener('resize', handleResize)
}
})UserProfile.vueapi-client.jsdate-utils.jsUserType.ts// 好的示例
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'Home',
component: () => import('@/pages/Home.vue'),
meta: {
title: '首页',
requiresAuth: false
}
},
{
path: '/user/:id',
name: 'UserDetail',
component: () => import('@/pages/UserDetail.vue'),
props: true,
meta: {
title: '用户详情',
requiresAuth: true
}
}
]
})// 好的示例
// 全局前置守卫
router.beforeEach((to, from, next) => {
// 设置页面标题
document.title = to.meta.title || 'App'
// 登录验证
const requiresAuth = to.meta.requiresAuth
const isLoggedIn = localStorage.getItem('token')
if (requiresAuth && !isLoggedIn) {
next('/login')
} else {
next()
}
})
// 全局后置守卫
router.afterEach((to, from) => {
// 记录路由跳转
console.log(`Navigated from ${from.path} to ${to.path}`)
})router.push() 和 router.replace() 进行编程式导航useRoute() 获取路由参数// 好的示例
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
// 编程式导航
const navigateToUser = (userId) => {
router.push({
name: 'UserDetail',
params: { id: userId }
})
}
// 获取路由参数
const userId = route.params.iduser-store.ts// 好的示例
import { defineStore } from 'pinia'
import { userApi } from '@/services/api'
interface User {
id: number
name: string
email: string
}
interface UserState {
users: User[]
loading: boolean
error: string | null
}
export const useUserStore = defineStore('user', {
state: (): UserState => ({
users: [],
loading: false,
error: null
}),
getters: {
/**
* 获取活跃用户数量
*/
activeUserCount: (state) => {
return state.users.length
},
/**
* 根据 ID 获取用户
*/
getUserById: (state) => (id: number) => {
return state.users.find(user => user.id === id)
}
},
actions: {
/**
* 获取用户列表
*/
async fetchUsers() {
this.loading = true
this.error = null
try {
const response = await userApi.getUsers()
this.users = response.data
} catch (error) {
this.error = 'Failed to fetch users'
console.error(error)
} finally {
this.loading = false
}
},
/**
* 添加用户
*/
async addUser(user: Omit<User, 'id'>) {
this.loading = true
this.error = null
try {
const response = await userApi.createUser(user)
this.users.push(response.data)
return response.data
} catch (error) {
this.error = 'Failed to add user'
console.error(error)
throw error
} finally {
this.loading = false
}
}
}
})v-memo 指令缓存模板片段v-once 指令v-memo 指令缓存计算结果shallowRef 和 shallowReactive 处理不需要深度响应的数据link rel="preload" 预加载关键资源npm run build 进行生产环境构建vue-cli-service build --report 分析构建结果.spec 或 .test 后缀// 好的示例
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import UserProfile from '@/components/UserProfile.vue'
describe('UserProfile.vue', () => {
it('should render user information', () => {
const userInfo = {
name: 'John',
email: 'john@example.com'
}
const wrapper = mount(UserProfile, {
props: {
userInfo
}
})
expect(wrapper.text()).toContain('John')
expect(wrapper.text()).toContain('john@example.com')
})
it('should emit update event when edit button is clicked', async () => {
const userInfo = {
name: 'John',
email: 'john@example.com'
}
const wrapper = mount(UserProfile, {
props: {
userInfo
}
})
await wrapper.find('button.edit-button').trigger('click')
expect(wrapper.emitted('update:userInfo')).toBeTruthy()
})
})app.config.errorHandler 捕获全局错误errorCaptured 生命周期钩子捕获组件错误use 开头命名