Vue3 寫法示例與規(guī)范詳細(xì)指南
一、項(xiàng)目結(jié)構(gòu)規(guī)范
1.推薦目錄結(jié)構(gòu)
src/ ├── assets/ # 靜態(tài)資源(圖片、字體等) ├── components/ # 公共組件(PascalCase命名) │ ├── Button.vue │ └── UserCard.vue ├── composables/ # 組合式函數(shù)(邏輯復(fù)用) │ └── useFetch.ts ├── router/ # 路由配置 │ └── index.ts ├── store/ # 狀態(tài)管理(Pinia) │ └── user.ts ├── utils/ # 工具函數(shù) │ └── format.ts ├── views/ # 頁面級(jí)組件 │ └── Home.vue ├── App.vue # 根組件 └── main.ts # 入口文件
2.命名規(guī)則
組件文件:PascalCase(如 UserProfile.vue)
文件夾:復(fù)數(shù)形式(如 components/ 而非 component/)
組合式函數(shù):useXxx 前綴(如 useAuth.ts)
二、代碼編寫規(guī)范
1. Script 部分(Composition API)
setup 語法糖
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import { fetchUser } from '@/api/user';
// 響應(yīng)式數(shù)據(jù)
const count = ref(0);
const user = ref<UserType | null>(null);
// 計(jì)算屬性
const doubleCount = computed(() => count.value * 2);
// 生命周期
onMounted(async () => {
user.value = await fetchUser(1);
});
// 類型定義
interface UserType {
id: number;
name: string;
}
</script>Props/Emits 類型化
const props = defineProps<{
modelValue: string;
disabled?: boolean;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void;
(e: 'submit'): void;
}>();2. Template 部分
語義化標(biāo)簽
<template>
<article class="article-card">
<header class="article-header">
<h2>{{ title }}</h2>
</header>
<main class="article-content">
<p>{{ content }}</p>
</main>
</article>
</template>條件渲染與列表
<template>
<!-- 避免 v-if + v-for 同級(jí) -->
<template v-if="users.length">
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
</template>
<p v-else>No users found</p>
</template>3. Style 部分
Scoped CSS
<style scoped>
.article-card {
border: 1px solid #eee;
transition: all 0.3s ease;
}
.article-card:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
</style>CSS 命名規(guī)范(BEM 示例)
.article-card {}
.article-card__header {}
.article-card__header--active {}三、高級(jí)特性規(guī)范
1. 組合式函數(shù)(Composables)
// composables/useCounter.ts
import { ref } from 'vue';
export function useCounter(initialValue = 0) {
const count = ref(initialValue);
const increment = () => count.value++;
const decrement = () => count.value--;
return { count, increment, decrement };
}2. 組件通信
1.父子組件通訊
1. 父?jìng)髯樱菏褂?props
父組件通過屬性(Props)向子組件傳遞數(shù)據(jù)。
父組件 (Parent.vue):
<template>
<div>
<ChildComponent :title="pageTitle" :user="currentUser" />
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import ChildComponent from './ChildComponent.vue'
const pageTitle = ref('歡迎來到我的應(yīng)用')
const currentUser = reactive({
name: '張三',
id: 123
})
</script>子組件 (ChildComponent.vue):
<template>
<div>
<h2>{{ title }}</h2>
<p>用戶: {{ user.name }} (ID: {{ user.id }})</p>
</div>
</template>
<script setup>
// 定義接收的 props
const props = defineProps({
title: {
type: String,
required: true
},
user: {
type: Object,
default: () => ({})
}
})
// 在模板中直接使用 props.title 和 props.user
// 注意:在 <script setup> 中,props 是一個(gè)對(duì)象,需要通過 props.xxx 訪問
</script>2. 子傳父:使用 emit
子組件通過觸發(fā)自定義事件向父組件傳遞數(shù)據(jù)。
子組件 (ChildComponent.vue):
<template>
<div>
<button @click="handleClick">點(diǎn)擊我通知父組件</button>
</div>
</template>
<script setup>
// 定義組件可以觸發(fā)的事件
const emit = defineEmits(['updateUser', 'customEvent'])
const handleClick = () => {
// 觸發(fā)事件,并傳遞數(shù)據(jù)
emit('updateUser', { id: 456, name: '李四' })
// 也可以觸發(fā)不帶參數(shù)的事件
emit('customEvent')
}
</script>父組件 (Parent.vue):
<template>
<div>
<ChildComponent
@updateUser="handleUserUpdate"
@customEvent="handleCustomEvent"
/>
<p>當(dāng)前用戶: {{ user.name }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'
const user = ref({ name: '王五', id: 789 })
const handleUserUpdate = (newUser) => {
// 接收子組件傳遞過來的數(shù)據(jù)
user.value = newUser
console.log('用戶已更新:', newUser)
}
const handleCustomEvent = () => {
console.log('自定義事件被觸發(fā)了')
}
</script>2.跨層級(jí)組件:provide/inject
當(dāng)組件嵌套層級(jí)很深,逐層傳遞 props 會(huì)非常繁瑣時(shí),可以使用 provide 和 inject。
使用 provide / inject
祖先組件提供數(shù)據(jù),后代組件(無論多深)注入并使用。
祖先組件 (App.vue 或 Layout.vue):
<template>
<div>
<DeeplyNestedChild />
</div>
</template>
<script setup>
import { provide, ref } from 'vue'
import DeeplyNestedChild from './components/DeeplyNestedChild.vue'
// 提供一個(gè)響應(yīng)式數(shù)據(jù)
const theme = ref('dark')
const appConfig = {
apiUrl: 'https://api.example.com',
version: '1.0.0'
}
// 第一個(gè)參數(shù)是 key (推薦使用 Symbol 或字符串),第二個(gè)參數(shù)是提供的值
provide('THEME', theme)
provide('APP_CONFIG', appConfig)
</script>后代組件 (DeeplyNestedChild.vue):
淺色版本
<template>
<div :class="theme">
<p>當(dāng)前主題: {{ theme }}</p>
<p>API 地址: {{ config.apiUrl }}</p>
</div>
</template>
<script setup>
import { inject } from 'vue'
// 注入數(shù)據(jù),第二個(gè)參數(shù)是默認(rèn)值(可選但推薦)
const theme = inject('THEME', 'light')
const config = inject('APP_CONFIG', {})
</script>注意
如果 provide 的是 ref 或 reactive 對(duì)象,inject 得到的數(shù)據(jù)會(huì)保持響應(yīng)性。
為避免命名沖突,建議使用 Symbol 作為 key:
淺色版本 // keys.js export const THEME_KEY = Symbol() export const CONFIG_KEY = Symbol() // 在 provide 和 inject 時(shí)使用這些 Symbol
3.其他通信方式
- $refs (子 -> 父): 父組件可以通過 ref獲取子組件的實(shí)例,從而直接調(diào)用子組件的方法或訪問其數(shù)據(jù)。這種方式會(huì)增加耦合度,應(yīng)謹(jǐn)慎使用。
- 插槽 (Slots): 主要用于內(nèi)容分發(fā),但結(jié)合作用域插槽 (Scoped Slots),可以實(shí)現(xiàn)父組件向子組件傳遞數(shù)據(jù),同時(shí)由父組件決定如何渲染。常用于列表、表格等組件。
- v-model: 是 props 和 emit 的語法糖,用于在表單組件上創(chuàng)建雙向綁定。
3. 性能優(yōu)化
虛擬滾動(dòng):長(zhǎng)列表使用 vue-virtual-scroller
計(jì)算屬性緩存:避免在模板中執(zhí)行復(fù)雜計(jì)算
響應(yīng)式優(yōu)化:對(duì)大型對(duì)象使用 shallowRef
四、工具鏈配置
1. ESLint 配置(.eslintrc.js)
module.exports = {
extends: [
'plugin:vue/vue3-recommended',
'@vue/typescript/recommended'
],
rules: {
'vue/multi-word-component-names': 'off', // 允許單文件組件名
'@typescript-eslint/no-explicit-any': 'warn'
}
};2. Prettier 配置(.prettierrc)
{
"semi": false,
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 100
}
3. Git 規(guī)范
提交信息格式:<_type>: <_subject>
強(qiáng)制檢查:使用 Husky + Commitlint
feat: 添加用戶登錄功能
fix: 修復(fù)表單驗(yàn)證錯(cuò)誤
chore: 更新依賴版本
五、反模式警示
避免混用 Options API 和 Composition API
<script>
export default {
data() { return { count: 0 } } // 不要與 setup() 混用
}
</script>
<script setup>
const count = ref(0); // 沖突
</script>
禁止直接修改 Props
<script setup>
const props = defineProps(['count']);
// 錯(cuò)誤方式
props.count++;
// 正確方式:通過 emits
const emit = defineEmits(['update:count']);
emit('update:count', props.count + 1);
</script>
避免深層響應(yīng)式
// 性能開銷大
const state = reactive({
user: {
profile: {
name: 'Alice'
}
}
});
// 優(yōu)化:對(duì)大型對(duì)象使用 shallowRef
const largeData = shallowRef({ /* ... */ });遵循以上規(guī)范可顯著提升代碼可維護(hù)性和團(tuán)隊(duì)協(xié)作效率,建議結(jié)合 Vue Style Guide 官方文檔使用。
到此這篇關(guān)于Vue3 寫法示例與規(guī)范指南的文章就介紹到這了,更多相關(guān)vue規(guī)范指南內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Element ui table表格內(nèi)容超出隱藏顯示省略號(hào)問題
這篇文章主要介紹了Element ui table表格內(nèi)容超出隱藏顯示省略號(hào)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,2023-11-11
vue-quill-editor富文本編輯器簡(jiǎn)單使用方法
這篇文章主要為大家詳細(xì)介紹了vue-quill-editor富文本編輯器簡(jiǎn)單使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09
vue實(shí)現(xiàn)登錄時(shí)滑塊驗(yàn)證
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)登錄時(shí)滑塊驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03

