frontend-dev
26
总安装量
17
周安装量
#14285
全站排名
安装命令
npx skills add https://github.com/doccker/cc-use-exp --skill frontend-dev
Agent 安装分布
gemini-cli
11
claude-code
11
opencode
10
codex
10
antigravity
8
cursor
8
Skill 文档
å端å¼åè§è
åèæ¥æº: Vue 宿¹é£æ ¼æåãElement Plus æä½³å®è·µ
UI 飿 ¼çº¦æ
ä¸¥æ ¼ç¦æ¢ï¼å¸¸è§ AI 飿 ¼ï¼
- â èç´«è²éè¹æ¸åãåå æè¾¹ãç»çææ
- â 大é¢ç§¯æ¸åãè¿å¤è£ 饰æ§å ä½å¾å½¢
- â èµåé£ãæé»ç§æé£ãAI 飿 ¼ UI
- â UI ææ¡ä¸ä½¿ç¨ emoji
åå°ç³»ç»ï¼é»è®¤é£æ ¼ï¼
| è¦ç´ | è¦æ± |
|---|---|
| ä¸»é¢ | 使ç¨ç»ä»¶åºé»è®¤ä¸»é¢ |
| é è² | é»ç½ç°ä¸ºä¸» + 1 个主è²ç¹ç¼ |
| 卿 | å å¶ï¼ä» ä¿çå¿ è¦äº¤äºåé¦ |
ææ¯æ
| å±çº§ | Vueï¼é¦éï¼ | Reactï¼å¤éï¼ |
|---|---|---|
| æ¡æ¶ | Vue 3 + TypeScript | React 18 + TypeScript |
| æå»º | Vite | Vite |
| è·¯ç± | Vue Router 4 | React Router 6 |
| ç¶æ | Pinia | Zustand |
| UI åº | Element Plus | Ant Design |
Vue ç¼ç è§è
ç»ä»¶åºç¡
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import type { User } from '@/types'
// Props & Emits
const props = defineProps<{ userId: number }>()
const emit = defineEmits<{ (e: 'update', value: string): void }>()
// ååºå¼ç¶æ
const loading = ref(false)
const user = ref<User | null>(null)
// 计ç®å±æ§
const displayName = computed(() => user.value?.name ?? 'æªç¥ç¨æ·')
// çå½å¨æ
onMounted(async () => { await fetchUser() })
// æ¹æ³
async function fetchUser() {
loading.value = true
try {
user.value = await api.getUser(props.userId)
} finally {
loading.value = false
}
}
</script>
<template>
<div class="user-card">
<h3>{{ displayName }}</h3>
</div>
</template>
<style scoped>
.user-card { padding: 16px; }
</style>
å½å约å®
| ç±»å | çº¦å® | ç¤ºä¾ |
|---|---|---|
| ç»ä»¶æä»¶ | PascalCase.vue | UserCard.vue |
| Composables | useXxx.ts | useAuth.ts |
| Store | useXxxStore.ts | useUserStore.ts |
ç¶æç®¡çï¼Piniaï¼
// stores/user.ts
export const useUserStore = defineStore('user', () => {
const user = ref<User | null>(null)
const token = ref<string>('')
const isLoggedIn = computed(() => !!token.value)
async function login(username: string, password: string) {
const res = await api.login(username, password)
token.value = res.token
user.value = res.user
}
return { user, token, isLoggedIn, login }
})
交äºç¶æå¤ç
å¿ é¡»å¤ççç¶æ: loadingãemptyãerrorãdisabledãsubmitting
<template>
<el-skeleton v-if="loading" :rows="5" animated />
<el-result v-else-if="error" icon="error" :title="error">
<template #extra>
<el-button @click="fetchData">éè¯</el-button>
</template>
</el-result>
<el-empty v-else-if="list.length === 0" description="ææ æ°æ®" />
<template v-else>
<!-- æ£å¸¸å
容 -->
</template>
</template>
TypeScript è§è
// types/user.ts
export interface User {
id: number
username: string
role: 'admin' | 'user'
}
export interface ApiResponse<T = unknown> {
code: number
message: string
data: T
}
æ§è½ä¼å
| åºæ¯ | æ¹æ¡ |
|---|---|
| 大å表 | èææ»å¨ |
| è·¯ç± | æå è½½ () => import() |
| è®¡ç® | ä½¿ç¨ computed ç¼å |
| å¤§æ°æ® | ä½¿ç¨ shallowRef |
// è·¯ç±æå è½½
const routes = [
{ path: '/dashboard', component: () => import('@/views/Dashboard.vue') }
]
// 请æ±é²æ
import { useDebounceFn } from '@vueuse/core'
const debouncedSearch = useDebounceFn((keyword) => api.search(keyword), 300)
ç®å½ç»æ
src/
âââ api/ # API 请æ±
âââ components/ # éç¨ç»ä»¶
âââ composables/ # ç»åå¼å½æ°
âââ router/ # è·¯ç±é
ç½®
âââ stores/ # Pinia stores
âââ types/ # TypeScript ç±»å
âââ utils/ # å·¥å
·å½æ°
âââ views/ # 页é¢ç»ä»¶
âââ App.vue
âââ main.ts
详ç»åè
宿´è§èè§ references/frontend-style.mdï¼å
å«ï¼
- 宿´ UI 飿 ¼çº¦æ
- Vue 3 ç¼ç è§è详解
- Pinia ç¶æç®¡ç
- API 请æ±å°è£
- æ§è½ä¼å详解
ð æ¬åå¤éµå¾ªï¼
frontend-dev– [å ·ä½ç« è]