@umacloud/knowledge 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/00-governance/governance-capabilities.md +557 -0
  2. package/00-governance/knowledge-map.md +39 -0
  3. package/00-governance/maintenance-policy.md +76 -0
  4. package/00-governance/review-checklist.md +81 -0
  5. package/README.md +13 -0
  6. package/ai/01-standards/agent-development-complete.md +691 -0
  7. package/ai/01-standards/llm-application-complete.md +488 -0
  8. package/ai/01-standards/mlops-complete.md +798 -0
  9. package/ai/01-standards/prompt-engineering-complete.md +646 -0
  10. package/ai/01-standards/rag-architecture-complete.md +649 -0
  11. package/ai/02-playbooks/llm-evaluation-playbook.md +847 -0
  12. package/ai/03-checklists/ai-project-checklist.md +215 -0
  13. package/ai/04-antipatterns/ai-antipatterns.md +661 -0
  14. package/ai/05-cases/case-rag-production.md +147 -0
  15. package/ai/06-glossary/ai-glossary.md +162 -0
  16. package/ai/agent-evaluation-benchmark.md +53 -0
  17. package/ai/ai-agent-memory-context-management.md +41 -0
  18. package/ai/ai-cost-capacity-optimization-playbook.md +42 -0
  19. package/ai/ai-data-security-and-compliance-playbook.md +37 -0
  20. package/ai/ai-domain-index-and-checklist.md +40 -0
  21. package/ai/ai-governance-maturity-model.md +50 -0
  22. package/ai/ai-model-selection-and-routing-strategy.md +47 -0
  23. package/ai/ai-observability-and-oncall-runbook.md +52 -0
  24. package/ai/ai-rag-engineering-playbook.md +42 -0
  25. package/ai/ai-red-team-and-safety-evaluation.md +42 -0
  26. package/ai/ai-release-readiness-and-rollback-gate.md +42 -0
  27. package/ai/llm-agent-engineering-deep-dive.md +57 -0
  28. package/ai/prompt-and-tool-guardrails.md +52 -0
  29. package/api/01-standards/enterprise-api-standards.md +198 -0
  30. package/api/01-standards/rest-api-design-guide.md +63 -0
  31. package/api/02-playbooks/api-pagination-playbook.md +93 -0
  32. package/api/02-playbooks/graphql-production-playbook.md +176 -0
  33. package/api/03-checklists/api-review-checklist.md +55 -0
  34. package/api/04-antipatterns/api-antipatterns.md +112 -0
  35. package/architecture/01-standards/api-gateway-patterns.md +496 -0
  36. package/architecture/01-standards/cloud-native-patterns.md +644 -0
  37. package/architecture/01-standards/distributed-systems-patterns.md +591 -0
  38. package/architecture/01-standards/event-driven-architecture.md +595 -0
  39. package/architecture/01-standards/microservices-patterns-complete.md +968 -0
  40. package/architecture/01-standards/microservices-patterns.md +495 -0
  41. package/architecture/01-standards/system-design-interview.md +664 -0
  42. package/architecture/02-playbooks/microservices-patterns-playbook.md +137 -0
  43. package/architecture/02-playbooks/migration-playbook.md +780 -0
  44. package/architecture/02-playbooks/system-design-playbook.md +779 -0
  45. package/architecture/03-checklists/architecture-decision-checklist.md +297 -0
  46. package/architecture/04-antipatterns/architecture-antipatterns.md +417 -0
  47. package/architecture/05-cases/case-netflix-microservices.md +413 -0
  48. package/architecture/06-glossary/architecture-glossary.md +164 -0
  49. package/architecture/adr-template-and-examples.md +38 -0
  50. package/architecture/api-gateway-deep-dive.md +1291 -0
  51. package/architecture/configuration-management.md +1162 -0
  52. package/architecture/distributed-transactions.md +1220 -0
  53. package/architecture/microservices-complete.md +735 -0
  54. package/architecture/resilience-and-disaster-patterns.md +37 -0
  55. package/architecture/service-governance.md +1198 -0
  56. package/architecture/system-architecture-deep-dive.md +37 -0
  57. package/backend/01-standards/analytics-and-growth.md +65 -0
  58. package/backend/01-standards/api-and-error-conventions.md +120 -0
  59. package/backend/01-standards/application-layering-and-packaging.md +160 -0
  60. package/backend/01-standards/auth-implementation.md +104 -0
  61. package/backend/01-standards/backend-framework-idioms.md +74 -0
  62. package/backend/01-standards/background-jobs-and-async.md +66 -0
  63. package/backend/01-standards/caching-strategies-complete.md +390 -0
  64. package/backend/01-standards/config-and-observability.md +77 -0
  65. package/backend/01-standards/data-modeling-and-persistence.md +94 -0
  66. package/backend/01-standards/django-complete.md +1765 -0
  67. package/backend/01-standards/email-and-notifications.md +64 -0
  68. package/backend/01-standards/fastapi-complete.md +925 -0
  69. package/backend/01-standards/file-upload-and-storage.md +66 -0
  70. package/backend/01-standards/graphql-api-complete.md +416 -0
  71. package/backend/01-standards/llm-application-standard.md +78 -0
  72. package/backend/01-standards/message-queue-patterns.md +379 -0
  73. package/backend/01-standards/microservices-and-distributed.md +78 -0
  74. package/backend/01-standards/nestjs-complete.md +2167 -0
  75. package/backend/01-standards/payment-integration.md +80 -0
  76. package/backend/01-standards/rate-limiting-complete.md +451 -0
  77. package/backend/01-standards/realtime-and-websocket.md +65 -0
  78. package/backend/01-standards/search-and-filtering.md +64 -0
  79. package/backend/01-standards/spring-boot-complete.md +445 -0
  80. package/backend/02-playbooks/api-design-playbook.md +718 -0
  81. package/backend/02-playbooks/email-send-playbook.md +130 -0
  82. package/backend/02-playbooks/file-upload-s3-playbook.md +153 -0
  83. package/backend/02-playbooks/typescript-enterprise-playbook.md +133 -0
  84. package/backend/02-playbooks/websocket-realtime-playbook.md +154 -0
  85. package/backend/03-checklists/api-launch-checklist.md +189 -0
  86. package/backend/04-antipatterns/backend-antipatterns.md +1051 -0
  87. package/blockchain/01-standards/blockchain-basics.md +557 -0
  88. package/blockchain/01-standards/smart-contract-development.md +1315 -0
  89. package/cicd/01-standards/deployment-and-delivery-standard.md +96 -0
  90. package/cicd/01-standards/github-actions-complete.md +473 -0
  91. package/cicd/01-standards/release-and-store-submission.md +75 -0
  92. package/cicd/02-playbooks/cicd-pipeline-playbook.md +144 -0
  93. package/cicd/02-playbooks/release-management-playbook.md +605 -0
  94. package/cicd/03-checklists/pipeline-security-checklist.md +168 -0
  95. package/cicd/04-antipatterns/cicd-antipatterns.md +589 -0
  96. package/cicd/05-cases/case-deployment-automation.md +221 -0
  97. package/cicd/05-cases/case-gitops-transformation.md +212 -0
  98. package/cicd/06-glossary/cicd-glossary.md +114 -0
  99. package/cicd/cicd-blueprint-deep-dive.md +38 -0
  100. package/cicd/release-readiness-gate.md +37 -0
  101. package/cloud-native/01-standards/container-security.md +741 -0
  102. package/cloud-native/01-standards/kubernetes-complete.md +812 -0
  103. package/cloud-native/02-playbooks/api-gateway-playbook.md +155 -0
  104. package/cloud-native/02-playbooks/gitops-with-argocd.md +760 -0
  105. package/cloud-native/02-playbooks/k8s-troubleshooting-playbook.md +1942 -0
  106. package/cloud-native/02-playbooks/message-queue-playbook.md +129 -0
  107. package/cloud-native/02-playbooks/multicloud-governance.md +726 -0
  108. package/cloud-native/02-playbooks/serverless-patterns.md +788 -0
  109. package/cloud-native/02-playbooks/service-mesh-playbook.md +612 -0
  110. package/cloud-native/02-playbooks/terraform-iac-playbook.md +143 -0
  111. package/cloud-native/03-checklists/container-security-checklist.md +431 -0
  112. package/cloud-native/03-checklists/k8s-production-readiness-checklist.md +460 -0
  113. package/cloud-native/04-antipatterns/container-antipatterns.md +660 -0
  114. package/cloud-native/04-antipatterns/k8s-antipatterns.md +743 -0
  115. package/cloud-native/05-cases/case-k8s-migration.md +478 -0
  116. package/cloud-native/05-cases/case-k8s-scaling.md +642 -0
  117. package/cloud-native/05-cases/case-k8s-security-incident.md +397 -0
  118. package/cloud-native/06-glossary/cloud-native-glossary.md +337 -0
  119. package/cross-platform/01-standards/cross-platform-frameworks.md +83 -0
  120. package/cross-platform/01-standards/platform-selection-and-architecture.md +77 -0
  121. package/data/01-standards/elasticsearch-complete.md +2098 -0
  122. package/data/01-standards/postgresql-complete.md +1613 -0
  123. package/data/01-standards/redis-complete.md +1527 -0
  124. package/data/02-playbooks/database-optimization-playbook.md +403 -0
  125. package/data/02-playbooks/elasticsearch-production-playbook.md +132 -0
  126. package/data/03-checklists/database-launch-checklist.md +187 -0
  127. package/data/04-antipatterns/database-antipatterns.md +873 -0
  128. package/data/05-cases/case-database-migration.md +310 -0
  129. package/data/06-glossary/database-glossary.md +440 -0
  130. package/data/data-governance-and-modeling-deep-dive.md +39 -0
  131. package/data-engineering/01-standards/airflow-complete.md +523 -0
  132. package/data-engineering/01-standards/kafka-complete.md +1521 -0
  133. package/data-engineering/02-playbooks/spark-etl-playbook.md +496 -0
  134. package/data-engineering/03-checklists/pipeline-launch-checklist.md +194 -0
  135. package/data-engineering/04-antipatterns/data-pipeline-antipatterns.md +684 -0
  136. package/data-engineering/05-cases/case-real-time-pipeline.md +355 -0
  137. package/data-engineering/06-glossary/data-engineering-glossary.md +429 -0
  138. package/database/01-standards/database-schema-standards.md +147 -0
  139. package/database/02-playbooks/postgresql-optimization-quick.md +52 -0
  140. package/database/02-playbooks/postgresql-performance-optimization.md +58 -0
  141. package/database/02-playbooks/postgresql-production-playbook.md +146 -0
  142. package/database/02-playbooks/redis-caching-playbook.md +117 -0
  143. package/database/03-checklists/database-review-checklist.md +50 -0
  144. package/database/04-antipatterns/database-antipatterns.md +112 -0
  145. package/design/01-standards/ui-design-system-complete.md +423 -0
  146. package/design/02-playbooks/design-handoff-playbook.md +254 -0
  147. package/design/02-playbooks/design-review-playbook.md +388 -0
  148. package/design/03-checklists/design-review-checklist.md +246 -0
  149. package/design/04-antipatterns/design-antipatterns.md +378 -0
  150. package/design/05-cases/case-design-system-adoption.md +328 -0
  151. package/design/06-glossary/design-glossary.md +329 -0
  152. package/design/ui-full-lifecycle-cross-platform-playbook.md +571 -0
  153. package/design/ux-system-deep-dive.md +38 -0
  154. package/design-systems/00-craft-rules.md +71 -0
  155. package/design-systems/aesthetic-families.md +43 -0
  156. package/design-systems/anti-ai-slop.md +162 -0
  157. package/design-systems/bold-geometric.md +120 -0
  158. package/design-systems/brutalist-bold.md +103 -0
  159. package/design-systems/editorial-clean.md +109 -0
  160. package/design-systems/glass-aurora.md +108 -0
  161. package/design-systems/modern-minimal.md +145 -0
  162. package/design-systems/premium-luxury.md +106 -0
  163. package/design-systems/product-type-design-map.md +48 -0
  164. package/design-systems/soft-warm.md +123 -0
  165. package/design-systems/tech-utility.md +113 -0
  166. package/desktop/01-standards/desktop-app-standard.md +72 -0
  167. package/desktop/01-standards/desktop-design.md +71 -0
  168. package/development/00-governance/document-template.md +41 -0
  169. package/development/01-standards/api-versioning-strategies.md +432 -0
  170. package/development/01-standards/authentication-patterns-complete.md +479 -0
  171. package/development/01-standards/css-architecture-complete.md +550 -0
  172. package/development/01-standards/database-migration-strategies.md +484 -0
  173. package/development/01-standards/elasticsearch-complete.md +347 -0
  174. package/development/01-standards/git-complete.md +371 -0
  175. package/development/01-standards/golang-complete.md +1565 -0
  176. package/development/01-standards/graphql-complete.md +298 -0
  177. package/development/01-standards/javascript-bundlers-complete.md +469 -0
  178. package/development/01-standards/javascript-typescript-complete.md +528 -0
  179. package/development/01-standards/jest-complete.md +275 -0
  180. package/development/01-standards/linux-complete.md +234 -0
  181. package/development/01-standards/logging-observability-complete.md +526 -0
  182. package/development/01-standards/microservices-communication.md +502 -0
  183. package/development/01-standards/mongodb-complete.md +406 -0
  184. package/development/01-standards/oauth2-complete.md +285 -0
  185. package/development/01-standards/performance-optimization-complete.md +289 -0
  186. package/development/01-standards/playwright-complete.md +247 -0
  187. package/development/01-standards/postgresql-complete.md +456 -0
  188. package/development/01-standards/pytest-complete.md +340 -0
  189. package/development/01-standards/python-async-programming.md +902 -0
  190. package/development/01-standards/python-complete.md +956 -0
  191. package/development/01-standards/python-decorators-complete.md +799 -0
  192. package/development/01-standards/python-design-patterns.md +2854 -0
  193. package/development/01-standards/python-packaging-distribution.md +420 -0
  194. package/development/01-standards/python-testing-strategies.md +607 -0
  195. package/development/01-standards/python-web-frameworks-comparison.md +471 -0
  196. package/development/01-standards/redis-complete.md +317 -0
  197. package/development/01-standards/rest-api-complete.md +316 -0
  198. package/development/01-standards/rust-complete.md +578 -0
  199. package/development/01-standards/typescript-advanced-types.md +1513 -0
  200. package/development/01-standards/web-security-complete.md +292 -0
  201. package/development/02-playbooks/api-design-playbook.md +810 -0
  202. package/development/02-playbooks/database-migration-playbook.md +580 -0
  203. package/development/02-playbooks/debugging-playbook.md +692 -0
  204. package/development/02-playbooks/feature-delivery-playbook.md +430 -0
  205. package/development/02-playbooks/incident-hotfix-playbook.md +387 -0
  206. package/development/02-playbooks/performance-optimization-playbook.md +531 -0
  207. package/development/02-playbooks/performance-tuning-playbook.md +652 -0
  208. package/development/02-playbooks/refactor-playbook.md +403 -0
  209. package/development/02-playbooks/release-playbook.md +469 -0
  210. package/development/03-checklists/architecture-review-checklist.md +168 -0
  211. package/development/03-checklists/data-migration-checklist.md +157 -0
  212. package/development/03-checklists/oncall-handover-checklist.md +173 -0
  213. package/development/03-checklists/pr-checklist.md +158 -0
  214. package/development/03-checklists/production-readiness-checklist.md +190 -0
  215. package/development/03-checklists/release-readiness-checklist.md +154 -0
  216. package/development/03-checklists/security-review-checklist.md +182 -0
  217. package/development/04-antipatterns/api-antipatterns.md +657 -0
  218. package/development/04-antipatterns/architecture-antipatterns.md +686 -0
  219. package/development/04-antipatterns/backend-antipatterns.md +648 -0
  220. package/development/04-antipatterns/cicd-antipatterns.md +540 -0
  221. package/development/04-antipatterns/code-smell-antipatterns.md +571 -0
  222. package/development/04-antipatterns/data-antipatterns.md +658 -0
  223. package/development/04-antipatterns/database-antipatterns.md +578 -0
  224. package/development/04-antipatterns/frontend-antipatterns.md +635 -0
  225. package/development/04-antipatterns/reliability-antipatterns.md +700 -0
  226. package/development/04-antipatterns/security-antipatterns.md +747 -0
  227. package/development/05-cases/case-api-version-migration.md +428 -0
  228. package/development/05-cases/case-authorization-hardening.md +383 -0
  229. package/development/05-cases/case-bluegreen-rollback.md +466 -0
  230. package/development/05-cases/case-cache-snowball-protection.md +485 -0
  231. package/development/05-cases/case-ci-cd-pipeline.md +544 -0
  232. package/development/05-cases/case-database-scaling.md +500 -0
  233. package/development/05-cases/case-db-hotspot-optimization.md +487 -0
  234. package/development/05-cases/case-incident-mttr-reduction.md +563 -0
  235. package/development/05-cases/case-microservice-migration.md +375 -0
  236. package/development/05-cases/case-performance-optimization.md +406 -0
  237. package/development/05-cases/case-security-incident-response.md +345 -0
  238. package/development/06-glossary/full-stack-glossary.md +166 -0
  239. package/development/09-maturity/quarterly-audit-template.md +35 -0
  240. package/development/11-ui-excellence/ui-aesthetic-system.md +41 -0
  241. package/development/11-ui-excellence/ui-engineering-excellence.md +435 -0
  242. package/development/12-scenarios/development-scenarios-guide.md +565 -0
  243. package/development/13-implementation-assets/implementation-toolkit.md +282 -0
  244. package/development/13-implementation-assets/knowledge-gates-execution.md +43 -0
  245. package/development/14-full-lifecycle/software-lifecycle-gates.md +511 -0
  246. package/development/15-lifecycle-templates/project-templates-collection.md +791 -0
  247. package/development/api-contract-and-versioning-guide.md +36 -0
  248. package/development/api-governance-complete.md +43 -0
  249. package/development/backend-engineering-complete.md +43 -0
  250. package/development/code-review-quality-complete.md +43 -0
  251. package/development/concurrency-reliability-complete.md +43 -0
  252. package/development/database-engineering-complete.md +43 -0
  253. package/development/engineering-effectiveness-complete.md +43 -0
  254. package/development/engineering-standards-deep-dive.md +38 -0
  255. package/development/frontend-engineering-complete.md +43 -0
  256. package/development/performance-capacity-complete.md +43 -0
  257. package/development/refactor-migration-complete.md +42 -0
  258. package/development/refactoring-and-techdebt-playbook.md +37 -0
  259. package/development/security-in-development-complete.md +43 -0
  260. package/devops/01-standards/cicd-pipeline-complete.md +262 -0
  261. package/devops/01-standards/docker-complete.md +1490 -0
  262. package/devops/01-standards/github-actions-complete.md +337 -0
  263. package/devops/01-standards/kubernetes-complete.md +638 -0
  264. package/devops/01-standards/terraform-complete.md +2117 -0
  265. package/devops/02-playbooks/docker-compose-playbook.md +233 -0
  266. package/devops/02-playbooks/docker-k8s-production-playbook.md +186 -0
  267. package/devops/02-playbooks/docker-production-playbook.md +952 -0
  268. package/edge-iot/01-standards/edge-iot-complete.md +473 -0
  269. package/experts/architect/api-design.md +178 -0
  270. package/experts/architect/methodology.md +124 -0
  271. package/experts/architect/security.md +75 -0
  272. package/experts/backend-lead/methodology.md +216 -0
  273. package/experts/devops/methodology.md +160 -0
  274. package/experts/frontend-lead/methodology.md +178 -0
  275. package/experts/product-manager/industry/ecommerce.md +43 -0
  276. package/experts/product-manager/industry/saas.md +40 -0
  277. package/experts/product-manager/methodology.md +97 -0
  278. package/experts/qa-lead/methodology.md +123 -0
  279. package/experts/qa-lead/test-strategy.md +128 -0
  280. package/experts/uiux-designer/methodology.md +125 -0
  281. package/frontend/01-standards/accessibility-complete.md +532 -0
  282. package/frontend/01-standards/accessibility-standard.md +74 -0
  283. package/frontend/01-standards/admin-dashboard-and-crud.md +72 -0
  284. package/frontend/01-standards/design-tokens-complete.md +444 -0
  285. package/frontend/01-standards/forms-and-validation.md +77 -0
  286. package/frontend/01-standards/frontend-architecture-and-layering.md +119 -0
  287. package/frontend/01-standards/i18n-and-localization.md +65 -0
  288. package/frontend/01-standards/nextjs-complete.md +451 -0
  289. package/frontend/01-standards/react-complete.md +713 -0
  290. package/frontend/01-standards/react-hooks-complete-guide.md +1100 -0
  291. package/frontend/01-standards/react-hooks-complete.md +1171 -0
  292. package/frontend/01-standards/seo-and-web-vitals.md +77 -0
  293. package/frontend/01-standards/state-management-complete.md +444 -0
  294. package/frontend/01-standards/vue-complete.md +499 -0
  295. package/frontend/01-standards/vue3-complete.md +2002 -0
  296. package/frontend/01-standards/web-framework-best-practices.md +64 -0
  297. package/frontend/01-standards/web-performance-complete.md +495 -0
  298. package/frontend/02-playbooks/accessibility-a11y-playbook.md +161 -0
  299. package/frontend/02-playbooks/frontend-performance-playbook.md +707 -0
  300. package/frontend/02-playbooks/i18n-internationalization-playbook.md +120 -0
  301. package/frontend/02-playbooks/performance-optimization-playbook.md +163 -0
  302. package/frontend/02-playbooks/react-nextjs-production-playbook.md +167 -0
  303. package/frontend/02-playbooks/react-state-management-playbook.md +173 -0
  304. package/frontend/03-checklists/component-quality-checklist.md +166 -0
  305. package/frontend/03-checklists/frontend-launch-checklist.md +299 -0
  306. package/frontend/04-antipatterns/frontend-antipatterns.md +886 -0
  307. package/frontend/05-cases/case-performance-optimization.md +274 -0
  308. package/harmony/01-standards/harmonyos-arkts-standard.md +75 -0
  309. package/harmony/01-standards/harmonyos-design.md +65 -0
  310. package/high-quality-engineering-playbook.md +54 -0
  311. package/incident/01-standards/incident-response-complete.md +303 -0
  312. package/incident/02-playbooks/chaos-engineering-playbook.md +883 -0
  313. package/incident/02-playbooks/postmortem-playbook.md +398 -0
  314. package/incident/03-checklists/incident-readiness-checklist.md +181 -0
  315. package/incident/04-antipatterns/incident-antipatterns.md +490 -0
  316. package/incident/05-cases/case-cascade-failure.md +176 -0
  317. package/incident/06-glossary/incident-glossary.md +114 -0
  318. package/incident/postmortem-and-response-deep-dive.md +39 -0
  319. package/industries/ecommerce/ecommerce-complete.md +631 -0
  320. package/industries/education/education-complete.md +555 -0
  321. package/industries/fintech/fintech-complete.md +501 -0
  322. package/industries/gaming/gaming-complete.md +587 -0
  323. package/industries/healthcare/healthcare-complete.md +452 -0
  324. package/low-code/01-standards/low-code-complete.md +944 -0
  325. package/miniprogram/01-standards/ai-common-mistakes.md +61 -0
  326. package/miniprogram/01-standards/miniprogram-custom-navbar-capsule.md +77 -0
  327. package/miniprogram/01-standards/miniprogram-design.md +61 -0
  328. package/miniprogram/01-standards/miniprogram-standard.md +81 -0
  329. package/mobile/01-standards/android-material-design.md +70 -0
  330. package/mobile/01-standards/flutter-complete.md +384 -0
  331. package/mobile/01-standards/ios-design-hig.md +78 -0
  332. package/mobile/01-standards/mobile-app-standard.md +85 -0
  333. package/mobile/01-standards/react-native-complete.md +352 -0
  334. package/mobile/02-playbooks/mobile-cross-platform-playbook.md +175 -0
  335. package/mobile/02-playbooks/mobile-performance.md +473 -0
  336. package/mobile/03-checklists/mobile-release-checklist.md +234 -0
  337. package/mobile/04-antipatterns/mobile-antipatterns.md +798 -0
  338. package/mobile/05-cases/case-app-performance.md +500 -0
  339. package/mobile/05-cases/case-app-startup-optimization.md +218 -0
  340. package/mobile/06-glossary/mobile-glossary.md +484 -0
  341. package/observability/01-standards/observability-standards.md +103 -0
  342. package/observability/02-playbooks/prometheus-grafana-playbook.md +135 -0
  343. package/observability/02-playbooks/structured-logging-playbook.md +73 -0
  344. package/observability/03-checklists/observability-checklist.md +54 -0
  345. package/observability/04-antipatterns/observability-antipatterns.md +106 -0
  346. package/operations/01-standards/prometheus-monitoring-complete.md +1578 -0
  347. package/operations/02-playbooks/capacity-planning-playbook.md +620 -0
  348. package/operations/03-checklists/production-launch-checklist.md +365 -0
  349. package/operations/04-antipatterns/operations-antipatterns.md +664 -0
  350. package/operations/05-cases/case-sre-practices.md +581 -0
  351. package/operations/06-glossary/operations-glossary.md +120 -0
  352. package/operations/aiops-anomaly-detection.md +758 -0
  353. package/operations/capacity-planning.md +1061 -0
  354. package/operations/chaos-engineering.md +659 -0
  355. package/operations/incident-command-system.md +38 -0
  356. package/operations/observability-complete.md +442 -0
  357. package/operations/slo-sli-playbook.md +517 -0
  358. package/operations/sre-operations-deep-dive.md +39 -0
  359. package/package.json +8 -0
  360. package/performance/01-standards/performance-and-scalability.md +80 -0
  361. package/performance/01-standards/performance-standards.md +156 -0
  362. package/performance/02-playbooks/query-optimization-playbook.md +103 -0
  363. package/performance/03-checklists/performance-checklist.md +56 -0
  364. package/performance/04-antipatterns/performance-antipatterns.md +146 -0
  365. package/product/01-standards/product-management-complete.md +285 -0
  366. package/product/02-playbooks/feature-launch-playbook.md +207 -0
  367. package/product/02-playbooks/user-research-playbook.md +532 -0
  368. package/product/03-checklists/feature-launch-checklist.md +275 -0
  369. package/product/04-antipatterns/product-antipatterns.md +355 -0
  370. package/product/05-cases/case-mvp-to-scale.md +384 -0
  371. package/product/06-glossary/product-glossary.md +462 -0
  372. package/product/feature-prioritization-framework.md +40 -0
  373. package/product/kpi-and-metric-tree.md +37 -0
  374. package/product/product-discovery-and-prd-deep-dive.md +41 -0
  375. package/quantum/01-standards/quantum-complete.md +1186 -0
  376. package/security/01-standards/api-security-complete.md +511 -0
  377. package/security/01-standards/container-runtime-security.md +574 -0
  378. package/security/01-standards/data-protection-gdpr.md +543 -0
  379. package/security/01-standards/owasp-top10-complete.md +1890 -0
  380. package/security/01-standards/secure-coding-baseline.md +90 -0
  381. package/security/01-standards/supply-chain-security.md +441 -0
  382. package/security/01-standards/web-security-checklist.md +108 -0
  383. package/security/01-standards/zero-trust-architecture.md +521 -0
  384. package/security/02-playbooks/auth-sso-playbook.md +166 -0
  385. package/security/02-playbooks/incident-response-security-playbook.md +588 -0
  386. package/security/02-playbooks/owasp-api-security-playbook.md +129 -0
  387. package/security/02-playbooks/payment-integration-playbook.md +119 -0
  388. package/security/02-playbooks/penetration-testing-playbook.md +517 -0
  389. package/security/03-checklists/security-audit-checklist.md +356 -0
  390. package/security/04-antipatterns/security-coding-antipatterns.md +580 -0
  391. package/security/05-cases/case-log4shell-incident.md +537 -0
  392. package/security/05-cases/case-major-breaches.md +468 -0
  393. package/security/06-glossary/security-glossary.md +212 -0
  394. package/security/compliance-automation.md +993 -0
  395. package/security/container-security.md +680 -0
  396. package/security/devsecops-complete.md +426 -0
  397. package/security/sast-dast-sca.md +775 -0
  398. package/security/secrets-management.md +594 -0
  399. package/security/security-architecture-deep-dive.md +37 -0
  400. package/security/threat-modeling-stride-playbook.md +40 -0
  401. package/seed-templates/auth-system.md +59 -0
  402. package/seed-templates/blog-content.md +94 -0
  403. package/seed-templates/dashboard.md +89 -0
  404. package/seed-templates/docs-site.md +73 -0
  405. package/seed-templates/e-commerce.md +50 -0
  406. package/seed-templates/saas-landing.md +92 -0
  407. package/seed-templates/settings-page.md +51 -0
  408. package/testing/01-standards/test-strategy-and-layering.md +83 -0
  409. package/testing/01-standards/testing-strategy-complete.md +422 -0
  410. package/testing/01-standards/unit-testing-best-practices.md +118 -0
  411. package/testing/02-playbooks/e2e-testing-playbook.md +988 -0
  412. package/testing/02-playbooks/testing-strategy-playbook.md +126 -0
  413. package/testing/03-checklists/test-strategy-checklist.md +208 -0
  414. package/testing/04-antipatterns/testing-antipatterns.md +718 -0
  415. package/testing/05-cases/case-testing-transformation.md +300 -0
  416. package/testing/06-glossary/testing-glossary.md +110 -0
  417. package/testing/risk-based-test-matrix.md +36 -0
  418. package/testing/testing-strategy-deep-dive.md +37 -0
@@ -0,0 +1,2002 @@
1
+ ---
2
+ id: vue3-complete
3
+ title: Vue 3 完整知识体系
4
+ domain: frontend
5
+ category: 01-standards
6
+ difficulty: intermediate
7
+ tags: [complete, frontend, pinia, router, vue3, 响应式系统原理, 性能优化, 概述]
8
+ quality_score: 70
9
+ last_updated: 2026-06-15
10
+ ---
11
+ # Vue 3 完整知识体系
12
+
13
+ ## 概述
14
+
15
+ Vue 3 是 Vue.js 的最新主版本,于 2022 年正式成为默认版本。它带来了组合式 API(Composition API)、基于 Proxy 的响应式系统、更好的 TypeScript 支持、Teleport/Suspense 等新内置组件,以及显著的性能提升。Vue 3 的设计目标是更小的包体积、更快的渲染速度和更好的可维护性。
16
+
17
+ ### Vue 3 vs Vue 2 vs React
18
+
19
+ | 特性 | Vue 3 | Vue 2 | React 18 |
20
+ |------|-------|-------|----------|
21
+ | 响应式机制 | Proxy | Object.defineProperty | 不可变状态 + 调度器 |
22
+ | API 风格 | 组合式 API + 选项式 | 选项式 API | Hooks |
23
+ | 虚拟DOM | 编译时优化的 VDOM | 传统 VDOM | Fiber 架构 |
24
+ | TypeScript | 原生支持 | 需要额外配置 | 原生支持 |
25
+ | 包大小(min+gzip) | ~16KB | ~23KB | ~42KB(含ReactDOM) |
26
+ | 模板编译 | 编译时优化、静态提升 | 运行时编译 | JSX 转换 |
27
+ | 状态管理 | Pinia(官方) | Vuex | Redux/Zustand/Jotai |
28
+ | 路由 | Vue Router 4 | Vue Router 3 | React Router 6 |
29
+ | SSR/SSG | Nuxt 3 | Nuxt 2 | Next.js |
30
+ | 学习曲线 | 低-中 | 低 | 中 |
31
+ | 并发模式 | 无 | 无 | Concurrent Features |
32
+ | Fragment | 支持 | 不支持(需单根节点) | 支持 |
33
+
34
+ ### 核心升级亮点
35
+
36
+ - **组合式 API**: 逻辑复用和代码组织的终极方案,替代 mixins
37
+ - **`<script setup>`**: 编译时语法糖,减少样板代码
38
+ - **Proxy 响应式**: 检测属性新增/删除、数组索引变化,不再需要 `Vue.set`
39
+ - **Tree-shaking 友好**: 按需引入,未使用的功能不会打包
40
+ - **多根节点组件(Fragment)**: 模板不再限制为单一根元素
41
+
42
+ ---
43
+
44
+ ## 组合式 API
45
+
46
+ ### setup 与 `<script setup>`
47
+
48
+ `<script setup>` 是组合式 API 在单文件组件(SFC)中的编译时语法糖,是 Vue 3 推荐的写法:
49
+
50
+ ```vue
51
+ <script setup lang="ts">
52
+ import { ref, reactive, computed, watch, watchEffect, onMounted } from 'vue'
53
+
54
+ // 所有顶层绑定自动暴露给模板
55
+ const title = ref('Vue 3 知识体系')
56
+ const count = ref(0)
57
+
58
+ function increment() {
59
+ count.value++
60
+ }
61
+
62
+ onMounted(() => {
63
+ console.log('组件已挂载')
64
+ })
65
+ </script>
66
+
67
+ <template>
68
+ <h1>{{ title }}</h1>
69
+ <p>计数: {{ count }}</p>
70
+ <button @click="increment">+1</button>
71
+ </template>
72
+ ```
73
+
74
+ 对比传统 `setup()` 函数写法:
75
+
76
+ ```vue
77
+ <script lang="ts">
78
+ import { defineComponent, ref } from 'vue'
79
+
80
+ export default defineComponent({
81
+ setup() {
82
+ const count = ref(0)
83
+ const increment = () => { count.value++ }
84
+
85
+ // 必须显式返回要暴露的内容
86
+ return { count, increment }
87
+ }
88
+ })
89
+ </script>
90
+ ```
91
+
92
+ ### ref 与 reactive
93
+
94
+ ```vue
95
+ <script setup lang="ts">
96
+ import { ref, reactive, toRefs, toRef, isRef, unref } from 'vue'
97
+
98
+ // ref: 包装基本类型或对象,通过 .value 访问
99
+ const count = ref(0)
100
+ const message = ref('hello')
101
+ const user = ref({ name: 'Alice', age: 30 }) // 对象也可以用 ref
102
+
103
+ // reactive: 包装对象/数组,直接访问属性
104
+ const state = reactive({
105
+ items: [] as string[],
106
+ loading: false,
107
+ error: null as string | null
108
+ })
109
+
110
+ // 修改 ref
111
+ count.value++
112
+ message.value = 'world'
113
+
114
+ // 修改 reactive(直接操作属性)
115
+ state.loading = true
116
+ state.items.push('new item')
117
+
118
+ // toRefs: 将 reactive 对象的每个属性转为 ref,保持响应式
119
+ const { items, loading } = toRefs(state)
120
+ // loading.value === state.loading
121
+
122
+ // toRef: 转换单个属性
123
+ const errorRef = toRef(state, 'error')
124
+
125
+ // 工具函数
126
+ console.log(isRef(count)) // true
127
+ console.log(unref(count)) // 0 (自动解包)
128
+ </script>
129
+ ```
130
+
131
+ **ref vs reactive 选择指南**:
132
+ - 基本类型(string/number/boolean)只能用 `ref`
133
+ - 表单状态、复杂对象优先用 `reactive`
134
+ - 需要替换整个对象时用 `ref`(`reactive` 不能替换引用)
135
+ - composable 函数返回值推荐用 `ref`(解构不丢失响应式)
136
+
137
+ ### computed
138
+
139
+ ```vue
140
+ <script setup lang="ts">
141
+ import { ref, computed } from 'vue'
142
+
143
+ const firstName = ref('张')
144
+ const lastName = ref('三')
145
+
146
+ // 只读计算属性
147
+ const fullName = computed(() => `${firstName.value}${lastName.value}`)
148
+
149
+ // 可写计算属性
150
+ const fullNameWritable = computed({
151
+ get: () => `${firstName.value}${lastName.value}`,
152
+ set: (val: string) => {
153
+ firstName.value = val[0] || ''
154
+ lastName.value = val.slice(1) || ''
155
+ }
156
+ })
157
+
158
+ // 带调试的计算属性
159
+ const expensiveComputed = computed(() => {
160
+ // 复杂计算
161
+ return someHeavyCalculation()
162
+ }, {
163
+ onTrack(e) { console.log('依赖被追踪', e) },
164
+ onTrigger(e) { console.log('依赖变化触发重算', e) }
165
+ })
166
+ </script>
167
+ ```
168
+
169
+ ### watch 与 watchEffect
170
+
171
+ ```vue
172
+ <script setup lang="ts">
173
+ import { ref, reactive, watch, watchEffect, watchPostEffect } from 'vue'
174
+
175
+ const keyword = ref('')
176
+ const page = ref(1)
177
+ const state = reactive({ filters: { category: 'all', sort: 'date' } })
178
+
179
+ // 监听单个 ref
180
+ watch(keyword, (newVal, oldVal) => {
181
+ console.log(`关键词从 "${oldVal}" 变为 "${newVal}"`)
182
+ fetchResults(newVal)
183
+ })
184
+
185
+ // 监听多个源
186
+ watch([keyword, page], ([newKeyword, newPage], [oldKeyword, oldPage]) => {
187
+ fetchResults(newKeyword, newPage)
188
+ })
189
+
190
+ // 监听 reactive 对象的属性(需要用 getter)
191
+ watch(
192
+ () => state.filters.category,
193
+ (newCategory) => { console.log('分类变化:', newCategory) }
194
+ )
195
+
196
+ // 深度监听
197
+ watch(
198
+ () => state.filters,
199
+ (newFilters) => { console.log('筛选项变化:', newFilters) },
200
+ { deep: true }
201
+ )
202
+
203
+ // 立即执行
204
+ watch(keyword, (val) => { fetchResults(val) }, { immediate: true })
205
+
206
+ // watchEffect: 自动收集依赖,立即执行
207
+ const stop = watchEffect((onCleanup) => {
208
+ const controller = new AbortController()
209
+ fetchData(keyword.value, { signal: controller.signal })
210
+
211
+ onCleanup(() => {
212
+ controller.abort() // 清理副作用
213
+ })
214
+ })
215
+
216
+ // 停止监听
217
+ stop()
218
+
219
+ // watchPostEffect: DOM 更新后执行
220
+ watchPostEffect(() => {
221
+ // 此时可以安全访问更新后的 DOM
222
+ console.log(document.querySelector('#result')?.textContent)
223
+ })
224
+ </script>
225
+ ```
226
+
227
+ ### 生命周期钩子
228
+
229
+ ```vue
230
+ <script setup lang="ts">
231
+ import {
232
+ onBeforeMount,
233
+ onMounted,
234
+ onBeforeUpdate,
235
+ onUpdated,
236
+ onBeforeUnmount,
237
+ onUnmounted,
238
+ onActivated,
239
+ onDeactivated,
240
+ onErrorCaptured
241
+ } from 'vue'
242
+
243
+ onBeforeMount(() => { console.log('挂载前') })
244
+ onMounted(() => { console.log('挂载完成,DOM 可用') })
245
+ onBeforeUpdate(() => { console.log('更新前') })
246
+ onUpdated(() => { console.log('更新完成') })
247
+ onBeforeUnmount(() => { console.log('卸载前,清理定时器/事件') })
248
+ onUnmounted(() => { console.log('卸载完成') })
249
+
250
+ // KeepAlive 组件激活/停用
251
+ onActivated(() => { console.log('被 KeepAlive 激活') })
252
+ onDeactivated(() => { console.log('被 KeepAlive 停用') })
253
+
254
+ // 错误捕获
255
+ onErrorCaptured((err, instance, info) => {
256
+ console.error('子组件错误:', err, info)
257
+ return false // 阻止错误继续向上传播
258
+ })
259
+ </script>
260
+ ```
261
+
262
+ ### 组合式函数(Composables)
263
+
264
+ ```typescript
265
+ // composables/useFetch.ts
266
+ import { ref, watchEffect, type Ref } from 'vue'
267
+
268
+ interface UseFetchReturn<T> {
269
+ data: Ref<T | null>
270
+ error: Ref<string | null>
271
+ loading: Ref<boolean>
272
+ refetch: () => Promise<void>
273
+ }
274
+
275
+ export function useFetch<T = any>(url: Ref<string> | string): UseFetchReturn<T> {
276
+ const data = ref<T | null>(null) as Ref<T | null>
277
+ const error = ref<string | null>(null)
278
+ const loading = ref(false)
279
+
280
+ async function fetchData() {
281
+ loading.value = true
282
+ error.value = null
283
+ try {
284
+ const response = await fetch(typeof url === 'string' ? url : url.value)
285
+ if (!response.ok) throw new Error(`HTTP ${response.status}`)
286
+ data.value = await response.json()
287
+ } catch (e) {
288
+ error.value = (e as Error).message
289
+ } finally {
290
+ loading.value = false
291
+ }
292
+ }
293
+
294
+ watchEffect(() => {
295
+ fetchData()
296
+ })
297
+
298
+ return { data, error, loading, refetch: fetchData }
299
+ }
300
+
301
+ // composables/useDebounce.ts
302
+ import { ref, watch, type Ref } from 'vue'
303
+
304
+ export function useDebounce<T>(source: Ref<T>, delay = 300): Ref<T> {
305
+ const debounced = ref(source.value) as Ref<T>
306
+ let timer: ReturnType<typeof setTimeout>
307
+
308
+ watch(source, (val) => {
309
+ clearTimeout(timer)
310
+ timer = setTimeout(() => { debounced.value = val }, delay)
311
+ })
312
+
313
+ return debounced
314
+ }
315
+
316
+ // composables/useLocalStorage.ts
317
+ import { ref, watch, type Ref } from 'vue'
318
+
319
+ export function useLocalStorage<T>(key: string, defaultValue: T): Ref<T> {
320
+ const stored = localStorage.getItem(key)
321
+ const data = ref<T>(stored ? JSON.parse(stored) : defaultValue) as Ref<T>
322
+
323
+ watch(data, (val) => {
324
+ localStorage.setItem(key, JSON.stringify(val))
325
+ }, { deep: true })
326
+
327
+ return data
328
+ }
329
+ ```
330
+
331
+ 使用组合式函数:
332
+
333
+ ```vue
334
+ <script setup lang="ts">
335
+ import { ref, computed } from 'vue'
336
+ import { useFetch } from '@/composables/useFetch'
337
+ import { useDebounce } from '@/composables/useDebounce'
338
+
339
+ const keyword = ref('')
340
+ const debouncedKeyword = useDebounce(keyword, 500)
341
+ const apiUrl = computed(() => `/api/search?q=${debouncedKeyword.value}`)
342
+ const { data, loading, error } = useFetch(apiUrl)
343
+ </script>
344
+
345
+ <template>
346
+ <input v-model="keyword" placeholder="搜索..." />
347
+ <div v-if="loading">加载中...</div>
348
+ <div v-else-if="error">错误: {{ error }}</div>
349
+ <ul v-else>
350
+ <li v-for="item in data" :key="item.id">{{ item.name }}</li>
351
+ </ul>
352
+ </template>
353
+ ```
354
+
355
+ ---
356
+
357
+ ## 响应式系统原理
358
+
359
+ ### Proxy 代理机制
360
+
361
+ Vue 3 的响应式系统基于 ES6 Proxy,替代了 Vue 2 的 `Object.defineProperty`:
362
+
363
+ ```typescript
364
+ // 简化的响应式实现原理
365
+ function reactive<T extends object>(target: T): T {
366
+ const handler: ProxyHandler<T> = {
367
+ get(target, key, receiver) {
368
+ const result = Reflect.get(target, key, receiver)
369
+ track(target, key) // 依赖收集
370
+ // 深层响应式:访问嵌套对象时递归代理
371
+ if (typeof result === 'object' && result !== null) {
372
+ return reactive(result)
373
+ }
374
+ return result
375
+ },
376
+ set(target, key, value, receiver) {
377
+ const oldValue = Reflect.get(target, key, receiver)
378
+ const result = Reflect.set(target, key, value, receiver)
379
+ if (oldValue !== value) {
380
+ trigger(target, key) // 触发更新
381
+ }
382
+ return result
383
+ },
384
+ deleteProperty(target, key) {
385
+ const result = Reflect.deleteProperty(target, key)
386
+ trigger(target, key) // 删除属性也能检测
387
+ return result
388
+ }
389
+ }
390
+ return new Proxy(target, handler)
391
+ }
392
+ ```
393
+
394
+ ### 依赖收集与触发更新
395
+
396
+ ```typescript
397
+ // 简化的依赖收集系统
398
+ type Dep = Set<ReactiveEffect>
399
+ type KeyToDepMap = Map<string | symbol, Dep>
400
+ const targetMap = new WeakMap<object, KeyToDepMap>()
401
+
402
+ let activeEffect: ReactiveEffect | null = null
403
+
404
+ function track(target: object, key: string | symbol) {
405
+ if (!activeEffect) return
406
+ let depsMap = targetMap.get(target)
407
+ if (!depsMap) {
408
+ targetMap.set(target, (depsMap = new Map()))
409
+ }
410
+ let dep = depsMap.get(key)
411
+ if (!dep) {
412
+ depsMap.set(key, (dep = new Set()))
413
+ }
414
+ dep.add(activeEffect) // 将当前 effect 加入依赖集合
415
+ }
416
+
417
+ function trigger(target: object, key: string | symbol) {
418
+ const depsMap = targetMap.get(target)
419
+ if (!depsMap) return
420
+ const dep = depsMap.get(key)
421
+ if (dep) {
422
+ dep.forEach(effect => {
423
+ // 调度器:异步批量更新
424
+ if (effect.scheduler) {
425
+ effect.scheduler()
426
+ } else {
427
+ effect.run()
428
+ }
429
+ })
430
+ }
431
+ }
432
+ ```
433
+
434
+ ### ref 的实现原理
435
+
436
+ ```typescript
437
+ // ref 本质是带 value 属性的对象
438
+ class RefImpl<T> {
439
+ private _value: T
440
+ private _rawValue: T
441
+ public dep: Set<ReactiveEffect> = new Set()
442
+ public readonly __v_isRef = true
443
+
444
+ constructor(value: T) {
445
+ this._rawValue = value
446
+ this._value = isObject(value) ? reactive(value) : value
447
+ }
448
+
449
+ get value() {
450
+ trackRefValue(this) // 收集依赖
451
+ return this._value
452
+ }
453
+
454
+ set value(newVal: T) {
455
+ if (hasChanged(newVal, this._rawValue)) {
456
+ this._rawValue = newVal
457
+ this._value = isObject(newVal) ? reactive(newVal) : newVal
458
+ triggerRefValue(this) // 触发更新
459
+ }
460
+ }
461
+ }
462
+ ```
463
+
464
+ ---
465
+
466
+ ## 组件设计
467
+
468
+ ### Props 定义与验证
469
+
470
+ ```vue
471
+ <script setup lang="ts">
472
+ // 类型声明方式(推荐)
473
+ interface Props {
474
+ title: string
475
+ count?: number
476
+ items: string[]
477
+ status: 'active' | 'inactive' | 'pending'
478
+ callback?: (id: number) => void
479
+ }
480
+
481
+ const props = withDefaults(defineProps<Props>(), {
482
+ count: 0,
483
+ status: 'active'
484
+ })
485
+
486
+ // 使用 props
487
+ console.log(props.title, props.count)
488
+ </script>
489
+ ```
490
+
491
+ 运行时验证写法(适用于需要自定义验证器的场景):
492
+
493
+ ```vue
494
+ <script setup>
495
+ const props = defineProps({
496
+ age: {
497
+ type: Number,
498
+ required: true,
499
+ validator: (value) => value >= 0 && value <= 150
500
+ },
501
+ email: {
502
+ type: String,
503
+ default: '',
504
+ validator: (value) => !value || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
505
+ }
506
+ })
507
+ </script>
508
+ ```
509
+
510
+ ### Emits 事件声明
511
+
512
+ ```vue
513
+ <script setup lang="ts">
514
+ // 类型声明方式
515
+ const emit = defineEmits<{
516
+ (e: 'update', id: number, value: string): void
517
+ (e: 'delete', id: number): void
518
+ (e: 'submit'): void
519
+ }>()
520
+
521
+ // Vue 3.3+ 简写语法
522
+ const emit = defineEmits<{
523
+ update: [id: number, value: string]
524
+ delete: [id: number]
525
+ submit: []
526
+ }>()
527
+
528
+ function handleSave(id: number) {
529
+ emit('update', id, 'new value')
530
+ }
531
+ </script>
532
+ ```
533
+
534
+ ### Slots 插槽
535
+
536
+ ```vue
537
+ <!-- BaseCard.vue -->
538
+ <template>
539
+ <div class="card">
540
+ <!-- 默认插槽 -->
541
+ <div class="card-body">
542
+ <slot />
543
+ </div>
544
+
545
+ <!-- 具名插槽 -->
546
+ <div class="card-header" v-if="$slots.header">
547
+ <slot name="header" />
548
+ </div>
549
+
550
+ <!-- 作用域插槽:向父组件传递数据 -->
551
+ <div class="card-list">
552
+ <slot name="item" v-for="item in items" :key="item.id"
553
+ :item="item" :index="items.indexOf(item)" />
554
+ </div>
555
+ </div>
556
+ </template>
557
+
558
+ <script setup lang="ts">
559
+ interface Item { id: number; name: string }
560
+ defineProps<{ items: Item[] }>()
561
+ </script>
562
+ ```
563
+
564
+ 使用插槽:
565
+
566
+ ```vue
567
+ <template>
568
+ <BaseCard :items="products">
569
+ <template #header>
570
+ <h2>产品列表</h2>
571
+ </template>
572
+
573
+ <template #item="{ item, index }">
574
+ <div class="product-row">
575
+ {{ index + 1 }}. {{ item.name }}
576
+ </div>
577
+ </template>
578
+
579
+ <!-- 默认插槽 -->
580
+ <p>底部描述信息</p>
581
+ </BaseCard>
582
+ </template>
583
+ ```
584
+
585
+ ### Provide / Inject 依赖注入
586
+
587
+ ```typescript
588
+ // types/injection-keys.ts
589
+ import type { InjectionKey, Ref } from 'vue'
590
+
591
+ export interface UserContext {
592
+ user: Ref<{ name: string; role: string } | null>
593
+ login: (name: string) => void
594
+ logout: () => void
595
+ }
596
+
597
+ export const UserKey: InjectionKey<UserContext> = Symbol('user')
598
+ ```
599
+
600
+ ```vue
601
+ <!-- 祖先组件 provide -->
602
+ <script setup lang="ts">
603
+ import { ref, provide } from 'vue'
604
+ import { UserKey, type UserContext } from '@/types/injection-keys'
605
+
606
+ const user = ref<{ name: string; role: string } | null>(null)
607
+
608
+ const userContext: UserContext = {
609
+ user,
610
+ login: (name: string) => { user.value = { name, role: 'user' } },
611
+ logout: () => { user.value = null }
612
+ }
613
+
614
+ provide(UserKey, userContext)
615
+ </script>
616
+ ```
617
+
618
+ ```vue
619
+ <!-- 后代组件 inject -->
620
+ <script setup lang="ts">
621
+ import { inject } from 'vue'
622
+ import { UserKey } from '@/types/injection-keys'
623
+
624
+ const userCtx = inject(UserKey)
625
+ if (!userCtx) throw new Error('UserContext 未提供')
626
+
627
+ const { user, login, logout } = userCtx
628
+ </script>
629
+
630
+ <template>
631
+ <div v-if="user">
632
+ 欢迎, {{ user.name }}
633
+ <button @click="logout">退出</button>
634
+ </div>
635
+ <button v-else @click="login('张三')">登录</button>
636
+ </template>
637
+ ```
638
+
639
+ ### Teleport
640
+
641
+ ```vue
642
+ <template>
643
+ <button @click="showModal = true">打开弹窗</button>
644
+
645
+ <!-- 将内容传送到 body 下,脱离组件 DOM 层级 -->
646
+ <Teleport to="body">
647
+ <div v-if="showModal" class="modal-overlay" @click.self="showModal = false">
648
+ <div class="modal-content">
649
+ <h2>弹窗标题</h2>
650
+ <p>弹窗内容,渲染在 body 下但逻辑仍属于当前组件</p>
651
+ <button @click="showModal = false">关闭</button>
652
+ </div>
653
+ </div>
654
+ </Teleport>
655
+ </template>
656
+
657
+ <script setup lang="ts">
658
+ import { ref } from 'vue'
659
+ const showModal = ref(false)
660
+ </script>
661
+ ```
662
+
663
+ ### Suspense(实验性)
664
+
665
+ ```vue
666
+ <template>
667
+ <Suspense>
668
+ <!-- 默认插槽:异步组件 -->
669
+ <template #default>
670
+ <AsyncDashboard />
671
+ </template>
672
+
673
+ <!-- 后备插槽:加载状态 -->
674
+ <template #fallback>
675
+ <div class="loading-skeleton">
676
+ <div class="skeleton-header" />
677
+ <div class="skeleton-body" />
678
+ </div>
679
+ </template>
680
+ </Suspense>
681
+ </template>
682
+
683
+ <script setup>
684
+ import { defineAsyncComponent } from 'vue'
685
+
686
+ const AsyncDashboard = defineAsyncComponent(() =>
687
+ import('./components/Dashboard.vue')
688
+ )
689
+ </script>
690
+ ```
691
+
692
+ 异步 setup 组件(配合 Suspense 使用):
693
+
694
+ ```vue
695
+ <!-- Dashboard.vue -->
696
+ <script setup lang="ts">
697
+ // 顶层 await 使组件成为异步组件
698
+ const response = await fetch('/api/dashboard')
699
+ const dashboardData = await response.json()
700
+ </script>
701
+
702
+ <template>
703
+ <div>{{ dashboardData.title }}</div>
704
+ </template>
705
+ ```
706
+
707
+ ---
708
+
709
+ ## Vue Router 4
710
+
711
+ ### 基础配置
712
+
713
+ ```typescript
714
+ // router/index.ts
715
+ import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
716
+
717
+ const routes: RouteRecordRaw[] = [
718
+ {
719
+ path: '/',
720
+ name: 'Home',
721
+ component: () => import('@/views/Home.vue')
722
+ },
723
+ {
724
+ path: '/users',
725
+ name: 'Users',
726
+ component: () => import('@/views/Users.vue'),
727
+ meta: { requiresAuth: true, title: '用户管理' }
728
+ },
729
+ {
730
+ // 动态路由参数
731
+ path: '/users/:id',
732
+ name: 'UserDetail',
733
+ component: () => import('@/views/UserDetail.vue'),
734
+ props: true // 将路由参数作为 props 传入组件
735
+ },
736
+ {
737
+ // 嵌套路由
738
+ path: '/settings',
739
+ component: () => import('@/layouts/SettingsLayout.vue'),
740
+ children: [
741
+ { path: '', name: 'SettingsGeneral', component: () => import('@/views/settings/General.vue') },
742
+ { path: 'profile', name: 'SettingsProfile', component: () => import('@/views/settings/Profile.vue') },
743
+ { path: 'security', name: 'SettingsSecurity', component: () => import('@/views/settings/Security.vue') }
744
+ ]
745
+ },
746
+ {
747
+ // 捕获所有未匹配路由
748
+ path: '/:pathMatch(.*)*',
749
+ name: 'NotFound',
750
+ component: () => import('@/views/NotFound.vue')
751
+ }
752
+ ]
753
+
754
+ const router = createRouter({
755
+ history: createWebHistory(import.meta.env.BASE_URL),
756
+ routes,
757
+ scrollBehavior(to, from, savedPosition) {
758
+ if (savedPosition) return savedPosition
759
+ if (to.hash) return { el: to.hash, behavior: 'smooth' }
760
+ return { top: 0 }
761
+ }
762
+ })
763
+
764
+ export default router
765
+ ```
766
+
767
+ ### 路由守卫
768
+
769
+ ```typescript
770
+ // 全局前置守卫
771
+ router.beforeEach(async (to, from) => {
772
+ const authStore = useAuthStore()
773
+
774
+ // 设置页面标题
775
+ document.title = (to.meta.title as string) || '默认标题'
776
+
777
+ // 认证检查
778
+ if (to.meta.requiresAuth && !authStore.isAuthenticated) {
779
+ return { name: 'Login', query: { redirect: to.fullPath } }
780
+ }
781
+
782
+ // 权限检查
783
+ if (to.meta.requiredRole) {
784
+ const hasRole = authStore.user?.roles.includes(to.meta.requiredRole as string)
785
+ if (!hasRole) return { name: 'Forbidden' }
786
+ }
787
+ })
788
+
789
+ // 全局后置钩子
790
+ router.afterEach((to, from) => {
791
+ // 发送页面访问统计
792
+ analytics.trackPageView(to.fullPath)
793
+ })
794
+ ```
795
+
796
+ 组件内守卫:
797
+
798
+ ```vue
799
+ <script setup lang="ts">
800
+ import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
801
+
802
+ const hasUnsavedChanges = ref(false)
803
+
804
+ // 离开路由前确认
805
+ onBeforeRouteLeave((to, from) => {
806
+ if (hasUnsavedChanges.value) {
807
+ const answer = window.confirm('有未保存的更改,确定离开吗?')
808
+ if (!answer) return false
809
+ }
810
+ })
811
+
812
+ // 路由参数变化时(如 /users/1 -> /users/2)
813
+ onBeforeRouteUpdate(async (to, from) => {
814
+ const userId = to.params.id as string
815
+ await fetchUser(userId)
816
+ })
817
+ </script>
818
+ ```
819
+
820
+ ### 动态路由
821
+
822
+ ```typescript
823
+ // 运行时添加路由(权限路由场景)
824
+ async function initDynamicRoutes() {
825
+ const authStore = useAuthStore()
826
+ const menus = await fetchUserMenus(authStore.user!.id)
827
+
828
+ menus.forEach(menu => {
829
+ router.addRoute({
830
+ path: menu.path,
831
+ name: menu.name,
832
+ component: () => import(`@/views/${menu.component}.vue`),
833
+ meta: { title: menu.title, icon: menu.icon }
834
+ })
835
+ })
836
+ }
837
+
838
+ // 移除路由
839
+ const removeRoute = router.addRoute({ path: '/temp', component: TempView })
840
+ removeRoute() // 调用返回值移除
841
+
842
+ // 检查路由是否存在
843
+ router.hasRoute('UserDetail')
844
+ ```
845
+
846
+ ### 路由元信息与类型扩展
847
+
848
+ ```typescript
849
+ // types/router.d.ts
850
+ import 'vue-router'
851
+
852
+ declare module 'vue-router' {
853
+ interface RouteMeta {
854
+ requiresAuth?: boolean
855
+ requiredRole?: string
856
+ title?: string
857
+ icon?: string
858
+ keepAlive?: boolean
859
+ transition?: string
860
+ }
861
+ }
862
+ ```
863
+
864
+ ---
865
+
866
+ ## Pinia 状态管理
867
+
868
+ ### Store 定义
869
+
870
+ ```typescript
871
+ // stores/user.ts
872
+ import { defineStore } from 'pinia'
873
+ import { ref, computed } from 'vue'
874
+
875
+ // 组合式 API 风格(推荐)
876
+ export const useUserStore = defineStore('user', () => {
877
+ // state
878
+ const user = ref<{ id: number; name: string; role: string } | null>(null)
879
+ const token = ref<string | null>(localStorage.getItem('token'))
880
+ const permissions = ref<string[]>([])
881
+
882
+ // getters
883
+ const isAuthenticated = computed(() => !!token.value)
884
+ const isAdmin = computed(() => user.value?.role === 'admin')
885
+ const displayName = computed(() => user.value?.name || '游客')
886
+
887
+ // actions
888
+ async function login(username: string, password: string) {
889
+ const res = await fetch('/api/auth/login', {
890
+ method: 'POST',
891
+ headers: { 'Content-Type': 'application/json' },
892
+ body: JSON.stringify({ username, password })
893
+ })
894
+ if (!res.ok) throw new Error('登录失败')
895
+ const data = await res.json()
896
+ token.value = data.token
897
+ user.value = data.user
898
+ permissions.value = data.permissions
899
+ localStorage.setItem('token', data.token)
900
+ }
901
+
902
+ function logout() {
903
+ token.value = null
904
+ user.value = null
905
+ permissions.value = []
906
+ localStorage.removeItem('token')
907
+ }
908
+
909
+ function hasPermission(perm: string): boolean {
910
+ return permissions.value.includes(perm)
911
+ }
912
+
913
+ return {
914
+ user, token, permissions,
915
+ isAuthenticated, isAdmin, displayName,
916
+ login, logout, hasPermission
917
+ }
918
+ })
919
+ ```
920
+
921
+ 选项式 API 风格:
922
+
923
+ ```typescript
924
+ // stores/counter.ts
925
+ export const useCounterStore = defineStore('counter', {
926
+ state: () => ({
927
+ count: 0,
928
+ history: [] as number[]
929
+ }),
930
+ getters: {
931
+ doubleCount: (state) => state.count * 2,
932
+ lastThreeHistory: (state) => state.history.slice(-3)
933
+ },
934
+ actions: {
935
+ increment() {
936
+ this.count++
937
+ this.history.push(this.count)
938
+ },
939
+ async incrementAsync() {
940
+ await new Promise(resolve => setTimeout(resolve, 1000))
941
+ this.increment()
942
+ }
943
+ }
944
+ })
945
+ ```
946
+
947
+ ### Store 间交互
948
+
949
+ ```typescript
950
+ // stores/cart.ts
951
+ import { defineStore } from 'pinia'
952
+ import { useUserStore } from './user'
953
+
954
+ export const useCartStore = defineStore('cart', () => {
955
+ const items = ref<CartItem[]>([])
956
+ const userStore = useUserStore()
957
+
958
+ const total = computed(() =>
959
+ items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
960
+ )
961
+
962
+ // VIP 用户打折
963
+ const finalTotal = computed(() =>
964
+ userStore.isAdmin ? total.value * 0.9 : total.value
965
+ )
966
+
967
+ return { items, total, finalTotal }
968
+ })
969
+ ```
970
+
971
+ ### Pinia 插件
972
+
973
+ ```typescript
974
+ // plugins/pinia-logger.ts
975
+ import type { PiniaPluginContext } from 'pinia'
976
+
977
+ export function piniaLogger({ store }: PiniaPluginContext) {
978
+ store.$onAction(({ name, args, after, onError }) => {
979
+ const startTime = Date.now()
980
+ console.log(`[Store:${store.$id}] Action "${name}" 开始`, args)
981
+
982
+ after((result) => {
983
+ console.log(`[Store:${store.$id}] Action "${name}" 完成 (${Date.now() - startTime}ms)`, result)
984
+ })
985
+
986
+ onError((error) => {
987
+ console.error(`[Store:${store.$id}] Action "${name}" 失败`, error)
988
+ })
989
+ })
990
+ }
991
+
992
+ // 持久化插件
993
+ export function piniaPersist({ store }: PiniaPluginContext) {
994
+ const savedState = localStorage.getItem(`pinia-${store.$id}`)
995
+ if (savedState) {
996
+ store.$patch(JSON.parse(savedState))
997
+ }
998
+
999
+ store.$subscribe((mutation, state) => {
1000
+ localStorage.setItem(`pinia-${store.$id}`, JSON.stringify(state))
1001
+ })
1002
+ }
1003
+
1004
+ // main.ts 注册
1005
+ import { createPinia } from 'pinia'
1006
+ const pinia = createPinia()
1007
+ pinia.use(piniaLogger)
1008
+ pinia.use(piniaPersist)
1009
+ app.use(pinia)
1010
+ ```
1011
+
1012
+ ### 在组件中使用 Store
1013
+
1014
+ ```vue
1015
+ <script setup lang="ts">
1016
+ import { storeToRefs } from 'pinia'
1017
+ import { useUserStore } from '@/stores/user'
1018
+
1019
+ const userStore = useUserStore()
1020
+
1021
+ // storeToRefs 保持响应式(只解构 state 和 getters)
1022
+ const { user, isAuthenticated, displayName } = storeToRefs(userStore)
1023
+
1024
+ // actions 直接解构(不需要 storeToRefs)
1025
+ const { login, logout } = userStore
1026
+
1027
+ // 订阅状态变化
1028
+ userStore.$subscribe((mutation, state) => {
1029
+ console.log('状态变化:', mutation.type, mutation.storeId)
1030
+ })
1031
+ </script>
1032
+ ```
1033
+
1034
+ ---
1035
+
1036
+ ## 性能优化
1037
+
1038
+ ### 虚拟列表
1039
+
1040
+ ```vue
1041
+ <!-- VirtualList.vue -->
1042
+ <script setup lang="ts">
1043
+ import { ref, computed, onMounted, onUnmounted } from 'vue'
1044
+
1045
+ interface Props {
1046
+ items: any[]
1047
+ itemHeight: number
1048
+ containerHeight: number
1049
+ overscan?: number
1050
+ }
1051
+
1052
+ const props = withDefaults(defineProps<Props>(), { overscan: 5 })
1053
+
1054
+ const scrollTop = ref(0)
1055
+ const containerRef = ref<HTMLDivElement>()
1056
+
1057
+ const totalHeight = computed(() => props.items.length * props.itemHeight)
1058
+
1059
+ const startIndex = computed(() =>
1060
+ Math.max(0, Math.floor(scrollTop.value / props.itemHeight) - props.overscan)
1061
+ )
1062
+
1063
+ const endIndex = computed(() =>
1064
+ Math.min(
1065
+ props.items.length,
1066
+ Math.ceil((scrollTop.value + props.containerHeight) / props.itemHeight) + props.overscan
1067
+ )
1068
+ )
1069
+
1070
+ const visibleItems = computed(() =>
1071
+ props.items.slice(startIndex.value, endIndex.value).map((item, i) => ({
1072
+ ...item,
1073
+ _index: startIndex.value + i,
1074
+ _style: {
1075
+ position: 'absolute' as const,
1076
+ top: `${(startIndex.value + i) * props.itemHeight}px`,
1077
+ height: `${props.itemHeight}px`,
1078
+ width: '100%'
1079
+ }
1080
+ }))
1081
+ )
1082
+
1083
+ function onScroll(e: Event) {
1084
+ scrollTop.value = (e.target as HTMLDivElement).scrollTop
1085
+ }
1086
+ </script>
1087
+
1088
+ <template>
1089
+ <div
1090
+ ref="containerRef"
1091
+ :style="{ height: containerHeight + 'px', overflow: 'auto', position: 'relative' }"
1092
+ @scroll="onScroll"
1093
+ >
1094
+ <div :style="{ height: totalHeight + 'px', position: 'relative' }">
1095
+ <div v-for="item in visibleItems" :key="item._index" :style="item._style">
1096
+ <slot :item="item" :index="item._index" />
1097
+ </div>
1098
+ </div>
1099
+ </div>
1100
+ </template>
1101
+ ```
1102
+
1103
+ ### KeepAlive 缓存
1104
+
1105
+ ```vue
1106
+ <template>
1107
+ <router-view v-slot="{ Component, route }">
1108
+ <Transition :name="route.meta.transition || 'fade'" mode="out-in">
1109
+ <KeepAlive :include="cachedRoutes" :max="10">
1110
+ <component :is="Component" :key="route.fullPath" />
1111
+ </KeepAlive>
1112
+ </Transition>
1113
+ </router-view>
1114
+ </template>
1115
+
1116
+ <script setup lang="ts">
1117
+ import { computed } from 'vue'
1118
+ import { useRouter } from 'vue-router'
1119
+
1120
+ const router = useRouter()
1121
+
1122
+ const cachedRoutes = computed(() =>
1123
+ router.getRoutes()
1124
+ .filter(route => route.meta.keepAlive)
1125
+ .map(route => route.name as string)
1126
+ )
1127
+ </script>
1128
+ ```
1129
+
1130
+ ### 代码分割与懒加载
1131
+
1132
+ ```typescript
1133
+ // 路由级代码分割
1134
+ const routes = [
1135
+ {
1136
+ path: '/dashboard',
1137
+ component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Dashboard.vue')
1138
+ }
1139
+ ]
1140
+
1141
+ // 组件级懒加载
1142
+ import { defineAsyncComponent } from 'vue'
1143
+
1144
+ const HeavyChart = defineAsyncComponent({
1145
+ loader: () => import('@/components/HeavyChart.vue'),
1146
+ loadingComponent: LoadingSpinner,
1147
+ errorComponent: ErrorDisplay,
1148
+ delay: 200, // 延迟显示 loading(避免闪烁)
1149
+ timeout: 10000 // 超时时间
1150
+ })
1151
+
1152
+ // 条件懒加载
1153
+ const AdminPanel = defineAsyncComponent(() =>
1154
+ userStore.isAdmin
1155
+ ? import('@/components/AdminPanel.vue')
1156
+ : import('@/components/AccessDenied.vue')
1157
+ )
1158
+ ```
1159
+
1160
+ ### v-memo 优化
1161
+
1162
+ ```vue
1163
+ <template>
1164
+ <!-- v-memo: 仅当依赖值变化时重新渲染 -->
1165
+ <div v-for="item in largeList" :key="item.id" v-memo="[item.id, item.selected]">
1166
+ <span>{{ item.name }}</span>
1167
+ <span :class="{ active: item.selected }">{{ item.status }}</span>
1168
+ <!-- 只有 item.id 或 item.selected 变化才重新渲染此节点 -->
1169
+ </div>
1170
+ </template>
1171
+ ```
1172
+
1173
+ ### 其他优化技巧
1174
+
1175
+ ```vue
1176
+ <script setup lang="ts">
1177
+ import { shallowRef, shallowReactive, triggerRef, markRaw } from 'vue'
1178
+
1179
+ // shallowRef: 只追踪 .value 的变化,不深层响应
1180
+ const hugeList = shallowRef<Item[]>([])
1181
+ hugeList.value = [...newData] // 触发更新
1182
+ // hugeList.value[0].name = 'x' // 不会触发更新
1183
+ triggerRef(hugeList) // 手动触发更新
1184
+
1185
+ // shallowReactive: 只追踪顶层属性
1186
+ const state = shallowReactive({
1187
+ nested: { count: 0 } // nested.count 变化不会触发更新
1188
+ })
1189
+
1190
+ // markRaw: 标记对象永不转为响应式(如第三方库实例)
1191
+ const map = markRaw(new Map())
1192
+ const chart = markRaw(echarts.init(el))
1193
+ </script>
1194
+ ```
1195
+
1196
+ **Tree-shaking 最佳实践**:
1197
+ - 使用 `import { ref, computed } from 'vue'` 按需导入,不要 `import Vue from 'vue'`
1198
+ - Vite 默认支持 Tree-shaking,确保依赖提供 ESM 格式
1199
+ - 使用 `rollup-plugin-visualizer` 分析打包产物
1200
+
1201
+ ---
1202
+
1203
+ ## 测试
1204
+
1205
+ ### Vitest 单元测试
1206
+
1207
+ ```typescript
1208
+ // __tests__/composables/useFetch.spec.ts
1209
+ import { describe, it, expect, vi, beforeEach } from 'vitest'
1210
+ import { ref, nextTick } from 'vue'
1211
+ import { useFetch } from '@/composables/useFetch'
1212
+
1213
+ // mock fetch
1214
+ global.fetch = vi.fn()
1215
+
1216
+ describe('useFetch', () => {
1217
+ beforeEach(() => {
1218
+ vi.clearAllMocks()
1219
+ })
1220
+
1221
+ it('应当成功获取数据', async () => {
1222
+ const mockData = [{ id: 1, name: 'Item 1' }]
1223
+ ;(fetch as any).mockResolvedValueOnce({
1224
+ ok: true,
1225
+ json: () => Promise.resolve(mockData)
1226
+ })
1227
+
1228
+ const { data, loading, error } = useFetch('/api/items')
1229
+
1230
+ expect(loading.value).toBe(true)
1231
+ await nextTick()
1232
+ await vi.waitFor(() => expect(loading.value).toBe(false))
1233
+
1234
+ expect(data.value).toEqual(mockData)
1235
+ expect(error.value).toBeNull()
1236
+ })
1237
+
1238
+ it('应当处理请求错误', async () => {
1239
+ ;(fetch as any).mockResolvedValueOnce({ ok: false, status: 404 })
1240
+
1241
+ const { data, error } = useFetch('/api/not-found')
1242
+ await vi.waitFor(() => expect(error.value).toBeTruthy())
1243
+
1244
+ expect(data.value).toBeNull()
1245
+ expect(error.value).toContain('404')
1246
+ })
1247
+
1248
+ it('应当在 URL 变化时重新请求', async () => {
1249
+ ;(fetch as any).mockResolvedValue({
1250
+ ok: true,
1251
+ json: () => Promise.resolve([])
1252
+ })
1253
+
1254
+ const url = ref('/api/items?page=1')
1255
+ useFetch(url)
1256
+
1257
+ await nextTick()
1258
+ expect(fetch).toHaveBeenCalledTimes(1)
1259
+
1260
+ url.value = '/api/items?page=2'
1261
+ await nextTick()
1262
+ expect(fetch).toHaveBeenCalledTimes(2)
1263
+ })
1264
+ })
1265
+ ```
1266
+
1267
+ ### Vue Test Utils 组件测试
1268
+
1269
+ ```typescript
1270
+ // __tests__/components/TodoList.spec.ts
1271
+ import { describe, it, expect, vi } from 'vitest'
1272
+ import { mount, flushPromises } from '@vue/test-utils'
1273
+ import { createTestingPinia } from '@pinia/testing'
1274
+ import { nextTick } from 'vue'
1275
+ import TodoList from '@/components/TodoList.vue'
1276
+ import { useTodoStore } from '@/stores/todo'
1277
+
1278
+ describe('TodoList', () => {
1279
+ function createWrapper(options = {}) {
1280
+ return mount(TodoList, {
1281
+ global: {
1282
+ plugins: [
1283
+ createTestingPinia({
1284
+ createSpy: vi.fn,
1285
+ initialState: {
1286
+ todo: {
1287
+ items: [
1288
+ { id: 1, text: '学习 Vue 3', done: false },
1289
+ { id: 2, text: '写测试', done: true }
1290
+ ]
1291
+ }
1292
+ }
1293
+ })
1294
+ ]
1295
+ },
1296
+ ...options
1297
+ })
1298
+ }
1299
+
1300
+ it('渲染待办列表', () => {
1301
+ const wrapper = createWrapper()
1302
+ const items = wrapper.findAll('[data-testid="todo-item"]')
1303
+ expect(items).toHaveLength(2)
1304
+ expect(items[0].text()).toContain('学习 Vue 3')
1305
+ })
1306
+
1307
+ it('添加新待办', async () => {
1308
+ const wrapper = createWrapper()
1309
+ const store = useTodoStore()
1310
+
1311
+ const input = wrapper.find('input[data-testid="new-todo"]')
1312
+ await input.setValue('新任务')
1313
+ await wrapper.find('form').trigger('submit')
1314
+
1315
+ expect(store.addTodo).toHaveBeenCalledWith('新任务')
1316
+ })
1317
+
1318
+ it('切换完成状态', async () => {
1319
+ const wrapper = createWrapper()
1320
+ const store = useTodoStore()
1321
+
1322
+ const checkbox = wrapper.find('[data-testid="todo-checkbox-1"]')
1323
+ await checkbox.trigger('change')
1324
+
1325
+ expect(store.toggleTodo).toHaveBeenCalledWith(1)
1326
+ })
1327
+
1328
+ it('显示空状态提示', () => {
1329
+ const wrapper = mount(TodoList, {
1330
+ global: {
1331
+ plugins: [
1332
+ createTestingPinia({
1333
+ initialState: { todo: { items: [] } }
1334
+ })
1335
+ ]
1336
+ }
1337
+ })
1338
+
1339
+ expect(wrapper.find('[data-testid="empty-state"]').exists()).toBe(true)
1340
+ expect(wrapper.text()).toContain('暂无待办事项')
1341
+ })
1342
+ })
1343
+ ```
1344
+
1345
+ ### E2E 测试(Playwright)
1346
+
1347
+ ```typescript
1348
+ // e2e/todo.spec.ts
1349
+ import { test, expect } from '@playwright/test'
1350
+
1351
+ test.describe('待办应用', () => {
1352
+ test.beforeEach(async ({ page }) => {
1353
+ await page.goto('/')
1354
+ })
1355
+
1356
+ test('完整的待办流程', async ({ page }) => {
1357
+ // 添加待办
1358
+ await page.fill('[data-testid="new-todo"]', '学习 Playwright')
1359
+ await page.press('[data-testid="new-todo"]', 'Enter')
1360
+ await expect(page.locator('[data-testid="todo-item"]')).toHaveCount(1)
1361
+
1362
+ // 标记完成
1363
+ await page.click('[data-testid="todo-checkbox-1"]')
1364
+ await expect(page.locator('[data-testid="todo-item-1"]')).toHaveClass(/completed/)
1365
+
1366
+ // 筛选已完成
1367
+ await page.click('[data-testid="filter-completed"]')
1368
+ await expect(page.locator('[data-testid="todo-item"]')).toHaveCount(1)
1369
+
1370
+ // 删除
1371
+ await page.hover('[data-testid="todo-item-1"]')
1372
+ await page.click('[data-testid="delete-1"]')
1373
+ await expect(page.locator('[data-testid="empty-state"]')).toBeVisible()
1374
+ })
1375
+ })
1376
+ ```
1377
+
1378
+ ---
1379
+
1380
+ ## TypeScript 集成
1381
+
1382
+ ### 组件类型
1383
+
1384
+ ```typescript
1385
+ // types/components.ts
1386
+ import type { Component, DefineComponent } from 'vue'
1387
+
1388
+ // 全局组件类型声明
1389
+ declare module 'vue' {
1390
+ interface GlobalComponents {
1391
+ BaseButton: typeof import('@/components/BaseButton.vue')['default']
1392
+ BaseInput: typeof import('@/components/BaseInput.vue')['default']
1393
+ BaseModal: typeof import('@/components/BaseModal.vue')['default']
1394
+ }
1395
+ }
1396
+ ```
1397
+
1398
+ ### defineExpose 类型
1399
+
1400
+ ```vue
1401
+ <!-- ChildForm.vue -->
1402
+ <script setup lang="ts">
1403
+ import { ref } from 'vue'
1404
+
1405
+ const formData = ref({ name: '', email: '' })
1406
+
1407
+ function validate(): boolean {
1408
+ return formData.value.name.length > 0
1409
+ }
1410
+
1411
+ function reset() {
1412
+ formData.value = { name: '', email: '' }
1413
+ }
1414
+
1415
+ defineExpose({ validate, reset })
1416
+ </script>
1417
+ ```
1418
+
1419
+ ```vue
1420
+ <!-- ParentView.vue -->
1421
+ <script setup lang="ts">
1422
+ import { ref } from 'vue'
1423
+ import ChildForm from './ChildForm.vue'
1424
+
1425
+ const formRef = ref<InstanceType<typeof ChildForm>>()
1426
+
1427
+ function handleSubmit() {
1428
+ if (formRef.value?.validate()) {
1429
+ // 提交表单
1430
+ }
1431
+ }
1432
+ </script>
1433
+
1434
+ <template>
1435
+ <ChildForm ref="formRef" />
1436
+ <button @click="handleSubmit">提交</button>
1437
+ </template>
1438
+ ```
1439
+
1440
+ ### 泛型组件(Vue 3.3+)
1441
+
1442
+ ```vue
1443
+ <!-- GenericList.vue -->
1444
+ <script setup lang="ts" generic="T extends { id: number }">
1445
+ defineProps<{
1446
+ items: T[]
1447
+ selected?: T
1448
+ }>()
1449
+
1450
+ defineEmits<{
1451
+ select: [item: T]
1452
+ }>()
1453
+ </script>
1454
+
1455
+ <template>
1456
+ <ul>
1457
+ <li
1458
+ v-for="item in items"
1459
+ :key="item.id"
1460
+ :class="{ active: selected?.id === item.id }"
1461
+ @click="$emit('select', item)"
1462
+ >
1463
+ <slot :item="item" />
1464
+ </li>
1465
+ </ul>
1466
+ </template>
1467
+ ```
1468
+
1469
+ 使用泛型组件:
1470
+
1471
+ ```vue
1472
+ <script setup lang="ts">
1473
+ interface User { id: number; name: string; email: string }
1474
+ const users = ref<User[]>([])
1475
+ const selectedUser = ref<User>()
1476
+ </script>
1477
+
1478
+ <template>
1479
+ <!-- TypeScript 会推断 item 为 User 类型 -->
1480
+ <GenericList :items="users" :selected="selectedUser" @select="selectedUser = $event">
1481
+ <template #default="{ item }">
1482
+ {{ item.name }} - {{ item.email }}
1483
+ </template>
1484
+ </GenericList>
1485
+ </template>
1486
+ ```
1487
+
1488
+ ### tsconfig.json 推荐配置
1489
+
1490
+ ```json
1491
+ {
1492
+ "compilerOptions": {
1493
+ "target": "ES2020",
1494
+ "module": "ESNext",
1495
+ "moduleResolution": "bundler",
1496
+ "strict": true,
1497
+ "jsx": "preserve",
1498
+ "jsxImportSource": "vue",
1499
+ "resolveJsonModule": true,
1500
+ "isolatedModules": true,
1501
+ "esModuleInterop": true,
1502
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
1503
+ "skipLibCheck": true,
1504
+ "noEmit": true,
1505
+ "paths": {
1506
+ "@/*": ["./src/*"]
1507
+ },
1508
+ "types": ["vite/client", "vitest/globals"]
1509
+ },
1510
+ "include": ["src/**/*.ts", "src/**/*.vue", "src/**/*.d.ts"],
1511
+ "references": [{ "path": "./tsconfig.node.json" }]
1512
+ }
1513
+ ```
1514
+
1515
+ ---
1516
+
1517
+ ## SSR / SSG(Nuxt 3)
1518
+
1519
+ ### 项目初始化与目录结构
1520
+
1521
+ ```bash
1522
+ npx nuxi@latest init my-nuxt-app
1523
+ cd my-nuxt-app && npm install
1524
+ ```
1525
+
1526
+ ```
1527
+ my-nuxt-app/
1528
+ ├── app.vue # 应用入口
1529
+ ├── nuxt.config.ts # Nuxt 配置
1530
+ ├── pages/ # 文件系统路由
1531
+ │ ├── index.vue # /
1532
+ │ ├── about.vue # /about
1533
+ │ └── users/
1534
+ │ ├── index.vue # /users
1535
+ │ └── [id].vue # /users/:id
1536
+ ├── components/ # 自动导入的组件
1537
+ ├── composables/ # 自动导入的组合式函数
1538
+ ├── server/ # 服务端 API
1539
+ │ ├── api/
1540
+ │ │ └── users.ts # /api/users
1541
+ │ └── middleware/
1542
+ ├── layouts/ # 布局组件
1543
+ ├── middleware/ # 路由中间件
1544
+ ├── plugins/ # 插件
1545
+ └── public/ # 静态资源
1546
+ ```
1547
+
1548
+ ### 数据获取
1549
+
1550
+ ```vue
1551
+ <!-- pages/users/[id].vue -->
1552
+ <script setup lang="ts">
1553
+ const route = useRoute()
1554
+
1555
+ // useFetch: 自动处理 SSR hydration,避免重复请求
1556
+ const { data: user, pending, error } = await useFetch(
1557
+ `/api/users/${route.params.id}`,
1558
+ {
1559
+ key: `user-${route.params.id}`,
1560
+ transform: (data) => ({
1561
+ ...data,
1562
+ fullName: `${data.firstName} ${data.lastName}`
1563
+ })
1564
+ }
1565
+ )
1566
+
1567
+ // useAsyncData: 更灵活的数据获取
1568
+ const { data: posts } = await useAsyncData(
1569
+ `user-posts-${route.params.id}`,
1570
+ () => $fetch(`/api/users/${route.params.id}/posts`)
1571
+ )
1572
+
1573
+ // 仅客户端获取(不参与 SSR)
1574
+ const { data: analytics } = await useFetch('/api/analytics', {
1575
+ server: false,
1576
+ lazy: true
1577
+ })
1578
+ </script>
1579
+
1580
+ <template>
1581
+ <div v-if="pending">加载中...</div>
1582
+ <div v-else-if="error">加载失败: {{ error.message }}</div>
1583
+ <div v-else>
1584
+ <h1>{{ user?.fullName }}</h1>
1585
+ <article v-for="post in posts" :key="post.id">
1586
+ {{ post.title }}
1587
+ </article>
1588
+ </div>
1589
+ </template>
1590
+ ```
1591
+
1592
+ ### Server API
1593
+
1594
+ ```typescript
1595
+ // server/api/users/[id].get.ts
1596
+ import { defineEventHandler, getRouterParam, createError } from 'h3'
1597
+
1598
+ export default defineEventHandler(async (event) => {
1599
+ const id = getRouterParam(event, 'id')
1600
+
1601
+ const user = await prisma.user.findUnique({ where: { id: Number(id) } })
1602
+ if (!user) {
1603
+ throw createError({ statusCode: 404, statusMessage: '用户不存在' })
1604
+ }
1605
+
1606
+ return user
1607
+ })
1608
+
1609
+ // server/api/users/index.post.ts
1610
+ export default defineEventHandler(async (event) => {
1611
+ const body = await readBody(event)
1612
+
1613
+ // 验证
1614
+ if (!body.name || !body.email) {
1615
+ throw createError({ statusCode: 400, statusMessage: '缺少必填字段' })
1616
+ }
1617
+
1618
+ return await prisma.user.create({ data: body })
1619
+ })
1620
+ ```
1621
+
1622
+ ### Nuxt 配置
1623
+
1624
+ ```typescript
1625
+ // nuxt.config.ts
1626
+ export default defineNuxtConfig({
1627
+ devtools: { enabled: true },
1628
+
1629
+ // SSR / SSG 模式切换
1630
+ ssr: true,
1631
+ // 预渲染指定路由(SSG)
1632
+ routeRules: {
1633
+ '/': { prerender: true },
1634
+ '/about': { prerender: true },
1635
+ '/api/**': { cors: true, headers: { 'cache-control': 's-maxage=600' } },
1636
+ '/dashboard/**': { ssr: false } // 仅客户端渲染
1637
+ },
1638
+
1639
+ // 模块
1640
+ modules: [
1641
+ '@pinia/nuxt',
1642
+ '@nuxtjs/tailwindcss',
1643
+ '@vueuse/nuxt',
1644
+ '@nuxt/image'
1645
+ ],
1646
+
1647
+ // 运行时配置
1648
+ runtimeConfig: {
1649
+ dbUrl: process.env.DATABASE_URL, // 仅服务端可用
1650
+ public: {
1651
+ apiBase: process.env.API_BASE || '/api' // 客户端可用
1652
+ }
1653
+ },
1654
+
1655
+ // Vite 配置
1656
+ vite: {
1657
+ css: {
1658
+ preprocessorOptions: {
1659
+ scss: { additionalData: '@use "@/assets/scss/variables" as *;' }
1660
+ }
1661
+ }
1662
+ },
1663
+
1664
+ // Nitro 服务引擎
1665
+ nitro: {
1666
+ preset: 'node-server', // 或 'vercel', 'cloudflare', 'netlify'
1667
+ compressPublicAssets: true
1668
+ }
1669
+ })
1670
+ ```
1671
+
1672
+ ---
1673
+
1674
+ ## 常见陷阱与反模式
1675
+
1676
+ ### 1. 响应式丢失
1677
+
1678
+ ```typescript
1679
+ // 错误:解构 reactive 对象会丢失响应式
1680
+ const state = reactive({ count: 0, name: 'Vue' })
1681
+ let { count } = state // count 是普通变量,失去响应式
1682
+
1683
+ // 正确:使用 toRefs
1684
+ const { count, name } = toRefs(state)
1685
+ // 或直接使用 ref
1686
+ const count = ref(0)
1687
+ ```
1688
+
1689
+ ### 2. ref 忘记 .value
1690
+
1691
+ ```typescript
1692
+ // 错误:在 script 中忘记 .value
1693
+ const count = ref(0)
1694
+ console.log(count) // RefImpl 对象,不是 0
1695
+ if (count) { /* 永远为 true,因为 ref 对象是 truthy */ }
1696
+
1697
+ // 正确
1698
+ console.log(count.value) // 0
1699
+ if (count.value) { /* 正确判断 */ }
1700
+
1701
+ // 注意:模板中自动解包,不需要 .value
1702
+ // <template>{{ count }}</template> 正确
1703
+ ```
1704
+
1705
+ ### 3. reactive 整体替换
1706
+
1707
+ ```typescript
1708
+ // 错误:替换整个 reactive 对象会断开响应式连接
1709
+ let state = reactive({ items: [] })
1710
+ state = reactive({ items: [1, 2, 3] }) // 原有引用丢失
1711
+
1712
+ // 正确:修改属性而非替换引用
1713
+ const state = reactive({ items: [] as number[] })
1714
+ state.items = [1, 2, 3] // 修改属性,响应式保持
1715
+
1716
+ // 或者使用 ref
1717
+ const state = ref({ items: [] as number[] })
1718
+ state.value = { items: [1, 2, 3] } // ref 可以替换整个值
1719
+ ```
1720
+
1721
+ ### 4. watch 的陷阱
1722
+
1723
+ ```typescript
1724
+ // 错误:直接监听 reactive 对象的属性值
1725
+ const state = reactive({ count: 0 })
1726
+ watch(state.count, (val) => { /* 不生效 */ })
1727
+
1728
+ // 正确:使用 getter 函数
1729
+ watch(() => state.count, (val) => { /* 生效 */ })
1730
+
1731
+ // 错误:监听 ref 时加了 .value
1732
+ const count = ref(0)
1733
+ watch(count.value, (val) => { /* 不生效,因为传入的是原始值 0 */ })
1734
+
1735
+ // 正确:直接传 ref
1736
+ watch(count, (val) => { /* 正确 */ })
1737
+ ```
1738
+
1739
+ ### 5. 异步操作中的响应式
1740
+
1741
+ ```typescript
1742
+ // 错误:异步回调中 this 指向或作用域问题
1743
+ async function fetchData() {
1744
+ const data = ref<any>(null)
1745
+ // 如果组件在请求完成前卸载,这里可能导致内存泄漏
1746
+ const res = await fetch('/api/data')
1747
+ data.value = await res.json()
1748
+ return data
1749
+ }
1750
+
1751
+ // 正确:配合 watchEffect + 清理
1752
+ const data = ref<any>(null)
1753
+ watchEffect(async (onCleanup) => {
1754
+ const controller = new AbortController()
1755
+ onCleanup(() => controller.abort())
1756
+
1757
+ try {
1758
+ const res = await fetch('/api/data', { signal: controller.signal })
1759
+ data.value = await res.json()
1760
+ } catch (e) {
1761
+ if ((e as Error).name !== 'AbortError') throw e
1762
+ }
1763
+ })
1764
+ ```
1765
+
1766
+ ### 6. v-for 与 v-if 优先级
1767
+
1768
+ ```vue
1769
+ <!-- 错误:Vue 3 中 v-if 优先级高于 v-for,无法访问 v-for 的变量 -->
1770
+ <li v-for="item in items" v-if="item.active" :key="item.id">
1771
+ {{ item.name }}
1772
+ </li>
1773
+
1774
+ <!-- 正确:使用 computed 过滤或用 template 包裹 -->
1775
+ <li v-for="item in activeItems" :key="item.id">
1776
+ {{ item.name }}
1777
+ </li>
1778
+
1779
+ <!-- 或 -->
1780
+ <template v-for="item in items" :key="item.id">
1781
+ <li v-if="item.active">{{ item.name }}</li>
1782
+ </template>
1783
+ ```
1784
+
1785
+ ### 7. 组件注册陷阱
1786
+
1787
+ ```vue
1788
+ <script setup>
1789
+ // 错误:在 <script setup> 中用 app.component 全局注册
1790
+ // 没有导入就使用组件(会在运行时报错)
1791
+
1792
+ // 正确:直接 import 即可,<script setup> 自动注册
1793
+ import MyComponent from './MyComponent.vue'
1794
+ // 模板中直接使用 <MyComponent />
1795
+ </script>
1796
+ ```
1797
+
1798
+ ### 8. Props 修改
1799
+
1800
+ ```vue
1801
+ <script setup lang="ts">
1802
+ const props = defineProps<{ modelValue: string }>()
1803
+ const emit = defineEmits<{ 'update:modelValue': [value: string] }>()
1804
+
1805
+ // 错误:直接修改 prop
1806
+ // props.modelValue = 'new value' // Vue 会警告
1807
+
1808
+ // 正确:通过 emit 通知父组件
1809
+ function updateValue(val: string) {
1810
+ emit('update:modelValue', val)
1811
+ }
1812
+
1813
+ // 或使用 computed 代理(适用于 v-model 场景)
1814
+ const localValue = computed({
1815
+ get: () => props.modelValue,
1816
+ set: (val) => emit('update:modelValue', val)
1817
+ })
1818
+ </script>
1819
+
1820
+ <template>
1821
+ <input v-model="localValue" />
1822
+ </template>
1823
+ ```
1824
+
1825
+ ### 9. 内存泄漏
1826
+
1827
+ ```vue
1828
+ <script setup lang="ts">
1829
+ import { onMounted, onUnmounted } from 'vue'
1830
+
1831
+ // 错误:不清理副作用
1832
+ onMounted(() => {
1833
+ window.addEventListener('resize', handleResize)
1834
+ setInterval(pollData, 5000)
1835
+ })
1836
+
1837
+ // 正确:在 onUnmounted 中清理
1838
+ let intervalId: ReturnType<typeof setInterval>
1839
+
1840
+ onMounted(() => {
1841
+ window.addEventListener('resize', handleResize)
1842
+ intervalId = setInterval(pollData, 5000)
1843
+ })
1844
+
1845
+ onUnmounted(() => {
1846
+ window.removeEventListener('resize', handleResize)
1847
+ clearInterval(intervalId)
1848
+ })
1849
+ </script>
1850
+ ```
1851
+
1852
+ ### 10. 过度使用全局状态
1853
+
1854
+ ```typescript
1855
+ // 反模式:所有数据都放 Pinia store
1856
+ // 只有跨组件共享的状态才需要放 store
1857
+
1858
+ // 正确分层:
1859
+ // - 组件局部状态 → ref/reactive
1860
+ // - 父子通信 → props/emits
1861
+ // - 跨层级共享 → provide/inject
1862
+ // - 全局共享 → Pinia store
1863
+ ```
1864
+
1865
+ ---
1866
+
1867
+ ## 项目脚手架与工程化
1868
+
1869
+ ### Vite 项目创建
1870
+
1871
+ ```bash
1872
+ npm create vue@latest my-vue-app
1873
+ # 选择: TypeScript, Vue Router, Pinia, Vitest, ESLint, Prettier
1874
+
1875
+ cd my-vue-app
1876
+ npm install
1877
+ npm run dev
1878
+ ```
1879
+
1880
+ ### 推荐项目结构
1881
+
1882
+ ```
1883
+ src/
1884
+ ├── assets/ # 静态资源(图片、字体、全局样式)
1885
+ ├── components/ # 通用组件
1886
+ │ ├── base/ # 基础 UI 组件(Button, Input, Modal)
1887
+ │ └── business/ # 业务组件
1888
+ ├── composables/ # 组合式函数
1889
+ ├── layouts/ # 布局组件
1890
+ ├── pages/ (或 views/) # 页面组件
1891
+ ├── router/ # 路由配置
1892
+ ├── stores/ # Pinia stores
1893
+ ├── types/ # TypeScript 类型定义
1894
+ ├── utils/ # 工具函数
1895
+ ├── api/ # API 请求封装
1896
+ ├── plugins/ # Vue 插件
1897
+ ├── directives/ # 自定义指令
1898
+ ├── App.vue
1899
+ └── main.ts
1900
+ ```
1901
+
1902
+ ### ESLint + Prettier 配置
1903
+
1904
+ ```javascript
1905
+ // eslint.config.js (Flat Config)
1906
+ import pluginVue from 'eslint-plugin-vue'
1907
+ import vueTsEslintConfig from '@vue/eslint-config-typescript'
1908
+ import pluginVitest from '@vitest/eslint-plugin'
1909
+ import prettierConfig from '@vue/eslint-config-prettier'
1910
+
1911
+ export default [
1912
+ { name: 'app/files-to-lint', files: ['**/*.{ts,mts,tsx,vue}'] },
1913
+ { name: 'app/files-to-ignore', ignores: ['**/dist/**', '**/coverage/**'] },
1914
+ ...pluginVue.configs['flat/recommended'],
1915
+ ...vueTsEslintConfig(),
1916
+ { ...pluginVitest.configs.recommended, files: ['src/**/__tests__/*'] },
1917
+ prettierConfig
1918
+ ]
1919
+ ```
1920
+
1921
+ ---
1922
+
1923
+ ## 学习路径
1924
+
1925
+ ### 入门 (1-2 周)
1926
+ 1. 模板语法、指令(v-bind/v-on/v-model/v-for/v-if)
1927
+ 2. 组件基础(props/emits/slots)
1928
+ 3. 响应式基础(ref/reactive/computed)
1929
+ 4. 生命周期钩子
1930
+ 5. 事件处理与表单绑定
1931
+
1932
+ ### 进阶 (2-4 周)
1933
+ 1. 组合式 API 深入(watch/watchEffect/composables)
1934
+ 2. Vue Router 4(动态路由/守卫/嵌套路由)
1935
+ 3. Pinia 状态管理
1936
+ 4. TypeScript 集成
1937
+ 5. 组件设计模式(provide/inject/Teleport/Suspense)
1938
+
1939
+ ### 高级 (1-2 月)
1940
+ 1. 响应式系统原理(Proxy/依赖收集/调度器)
1941
+ 2. 虚拟 DOM 与编译优化
1942
+ 3. 性能优化(虚拟列表/KeepAlive/v-memo/shallowRef)
1943
+ 4. SSR/SSG(Nuxt 3)
1944
+ 5. 自定义渲染器与高级插件开发
1945
+
1946
+ ### 专家 (持续)
1947
+ 1. Vue 编译器源码
1948
+ 2. 自定义 Vite 插件
1949
+ 3. 大规模应用架构(微前端/Monorepo)
1950
+ 4. 设计系统构建
1951
+
1952
+ ## 参考资源
1953
+
1954
+ ### 官方文档
1955
+ - [Vue 3 官方文档](https://cn.vuejs.org/)
1956
+ - [Vue Router](https://router.vuejs.org/zh/)
1957
+ - [Pinia](https://pinia.vuejs.org/zh/)
1958
+ - [Nuxt 3](https://nuxt.com/)
1959
+ - [Vite](https://cn.vitejs.dev/)
1960
+
1961
+ ### 推荐资源
1962
+ - [VueUse](https://vueuse.org/) - 组合式工具集合
1963
+ - [Vue Macros](https://vue-macros.dev/) - 编译时宏扩展
1964
+ - [Vitest](https://vitest.dev/) - Vite 原生测试框架
1965
+
1966
+ ---
1967
+
1968
+ ## Agent Checklist
1969
+
1970
+ 使用本知识文件时,Agent 应确认以下要点:
1971
+
1972
+ - [ ] 项目使用 Vue 3 + `<script setup>` + TypeScript 的推荐写法
1973
+ - [ ] 响应式数据选择正确(ref 用于基本类型/需要替换的对象,reactive 用于复杂对象)
1974
+ - [ ] computed 用于派生状态,避免在模板中写复杂表达式
1975
+ - [ ] watch/watchEffect 正确清理副作用(onCleanup)
1976
+ - [ ] composable 函数命名以 `use` 前缀开头,返回 ref 而非 reactive
1977
+ - [ ] Props 使用 TypeScript 接口定义,设置合理的默认值
1978
+ - [ ] 组件事件使用 defineEmits 类型声明
1979
+ - [ ] 路由使用懒加载(`() => import(...)`)
1980
+ - [ ] 路由守卫中正确处理认证和权限逻辑
1981
+ - [ ] Pinia store 使用组合式 API 风格,通过 storeToRefs 解构
1982
+ - [ ] 大列表使用虚拟列表或分页,避免一次渲染数千 DOM 节点
1983
+ - [ ] 合理使用 KeepAlive 缓存频繁切换的组件
1984
+ - [ ] 使用 shallowRef/shallowReactive 优化大数据结构
1985
+ - [ ] 第三方库实例使用 markRaw 避免不必要的响应式代理
1986
+ - [ ] v-for 始终提供稳定的 key
1987
+ - [ ] 不直接修改 props,通过 emit 或 computed 代理
1988
+ - [ ] 组件卸载时清理所有副作用(事件监听/定时器/AbortController)
1989
+ - [ ] Nuxt 3 项目使用 useFetch/useAsyncData 获取数据,利用 SSR hydration
1990
+ - [ ] ESLint + Prettier 配置就绪,CI 中强制检查
1991
+ - [ ] 单元测试覆盖核心 composables 和业务组件
1992
+
1993
+ ---
1994
+
1995
+ **知识ID**: `vue3-complete`
1996
+ **版本**: v1.0
1997
+ **领域**: frontend
1998
+ **类型**: standards
1999
+ **难度**: intermediate
2000
+ **质量分**: 95
2001
+ **维护者**: frontend-team@umadev.com
2002
+ **最后更新**: 2026-03-28