mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-16 08:26:52 +08:00
feat: add Vue ecosystem review support
This commit is contained in:
parent
6865316ab3
commit
86e2a2061a
@ -11,7 +11,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ecc",
|
"name": "ecc",
|
||||||
"source": "./",
|
"source": "./",
|
||||||
"description": "Harness-native ECC operator layer - 64 agents, 262 skills, 84 legacy command shims, reusable hooks, rules, selective install profiles, and production-ready workflows for Claude Code, Codex, OpenCode, Cursor, and related agent harnesses",
|
"description": "Harness-native ECC operator layer - 65 agents, 263 skills, 85 legacy command shims, reusable hooks, rules, selective install profiles, and production-ready workflows for Claude Code, Codex, OpenCode, Cursor, and related agent harnesses",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Affaan Mustafa",
|
"name": "Affaan Mustafa",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ecc",
|
"name": "ecc",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"description": "Harness-native ECC plugin for engineering teams - 64 agents, 262 skills, 84 legacy command shims, reusable hooks, rules, MCP conventions, and operator workflows for Claude Code plus adjacent agent harnesses",
|
"description": "Harness-native ECC plugin for engineering teams - 65 agents, 263 skills, 85 legacy command shims, reusable hooks, rules, MCP conventions, and operator workflows for Claude Code plus adjacent agent harnesses",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Affaan Mustafa",
|
"name": "Affaan Mustafa",
|
||||||
"url": "https://x.com/affaanmustafa"
|
"url": "https://x.com/affaanmustafa"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Everything Claude Code (ECC) — Agent Instructions
|
# Everything Claude Code (ECC) — Agent Instructions
|
||||||
|
|
||||||
This is a **production-ready AI coding plugin** providing 64 specialized agents, 262 skills, 84 commands, and automated hook workflows for software development.
|
This is a **production-ready AI coding plugin** providing 65 specialized agents, 263 skills, 85 commands, and automated hook workflows for software development.
|
||||||
|
|
||||||
**Version:** 2.0.0
|
**Version:** 2.0.0
|
||||||
|
|
||||||
@ -149,9 +149,9 @@ Troubleshoot failures: check test isolation → verify mocks → fix implementat
|
|||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
agents/ — 64 specialized subagents
|
agents/ — 65 specialized subagents
|
||||||
skills/ — 262 workflow skills and domain knowledge
|
skills/ — 263 workflow skills and domain knowledge
|
||||||
commands/ — 84 slash commands
|
commands/ — 85 slash commands
|
||||||
hooks/ — Trigger-based automations
|
hooks/ — Trigger-based automations
|
||||||
rules/ — Always-follow guidelines (common + per-language)
|
rules/ — Always-follow guidelines (common + per-language)
|
||||||
scripts/ — Cross-platform Node.js utilities
|
scripts/ — Cross-platform Node.js utilities
|
||||||
|
|||||||
18
README.md
18
README.md
@ -154,7 +154,7 @@ Stable graduation of the 2.0 line: 261 skills, the control-pane substrate (sessi
|
|||||||
### v2.0.0-rc.1 — Surface Refresh, Operator Workflows, and ECC 2.0 Alpha (Apr 2026)
|
### v2.0.0-rc.1 — Surface Refresh, Operator Workflows, and ECC 2.0 Alpha (Apr 2026)
|
||||||
|
|
||||||
- **Dashboard GUI** — New Tkinter-based desktop application (`ecc_dashboard.py` or `npm run dashboard`) with dark/light theme toggle, font customization, and project logo in header and taskbar.
|
- **Dashboard GUI** — New Tkinter-based desktop application (`ecc_dashboard.py` or `npm run dashboard`) with dark/light theme toggle, font customization, and project logo in header and taskbar.
|
||||||
- **Public surface synced to the live repo** — metadata, catalog counts, plugin manifests, and install-facing docs now match the actual OSS surface: 64 agents, 262 skills, and 84 legacy command shims.
|
- **Public surface synced to the live repo** — metadata, catalog counts, plugin manifests, and install-facing docs now match the actual OSS surface: 65 agents, 263 skills, and 85 legacy command shims.
|
||||||
- **Operator and outbound workflow expansion** — `brand-voice`, `social-graph-ranker`, `connections-optimizer`, `customer-billing-ops`, `ecc-tools-cost-audit`, `google-workspace-ops`, `project-flow-ops`, and `workspace-surface-audit` round out the operator lane.
|
- **Operator and outbound workflow expansion** — `brand-voice`, `social-graph-ranker`, `connections-optimizer`, `customer-billing-ops`, `ecc-tools-cost-audit`, `google-workspace-ops`, `project-flow-ops`, and `workspace-surface-audit` round out the operator lane.
|
||||||
- **Media and launch tooling** — `manim-video`, `remotion-video-creation`, and upgraded social publishing surfaces make technical explainers and launch content part of the same system.
|
- **Media and launch tooling** — `manim-video`, `remotion-video-creation`, and upgraded social publishing surfaces make technical explainers and launch content part of the same system.
|
||||||
- **Framework and product surface growth** — `nestjs-patterns`, richer Codex/OpenCode install surfaces, and expanded cross-harness packaging keep the repo usable beyond Claude Code alone.
|
- **Framework and product surface growth** — `nestjs-patterns`, richer Codex/OpenCode install surfaces, and expanded cross-harness packaging keep the repo usable beyond Claude Code alone.
|
||||||
@ -425,7 +425,7 @@ If you stacked methods, clean up in this order:
|
|||||||
/plugin list ecc@ecc
|
/plugin list ecc@ecc
|
||||||
```
|
```
|
||||||
|
|
||||||
**That's it!** You now have access to 64 agents, 262 skills, and 84 legacy command shims.
|
**That's it!** You now have access to 65 agents, 263 skills, and 85 legacy command shims.
|
||||||
|
|
||||||
### Dashboard GUI
|
### Dashboard GUI
|
||||||
|
|
||||||
@ -555,7 +555,7 @@ ECC/
|
|||||||
| |-- plugin.json # Plugin metadata and component paths
|
| |-- plugin.json # Plugin metadata and component paths
|
||||||
| |-- marketplace.json # Marketplace catalog for /plugin marketplace add
|
| |-- marketplace.json # Marketplace catalog for /plugin marketplace add
|
||||||
|
|
|
|
||||||
|-- agents/ # 64 specialized subagents for delegation
|
|-- agents/ # 65 specialized subagents for delegation
|
||||||
| |-- planner.md # Feature implementation planning
|
| |-- planner.md # Feature implementation planning
|
||||||
| |-- architect.md # System design decisions
|
| |-- architect.md # System design decisions
|
||||||
| |-- tdd-guide.md # Test-driven development
|
| |-- tdd-guide.md # Test-driven development
|
||||||
@ -1507,9 +1507,9 @@ The configuration is automatically detected from `.opencode/opencode.json`.
|
|||||||
|
|
||||||
| Feature | Claude Code | OpenCode | Status |
|
| Feature | Claude Code | OpenCode | Status |
|
||||||
|---------|---------------------|----------|--------|
|
|---------|---------------------|----------|--------|
|
||||||
| Agents | PASS: 64 agents | PASS: 12 agents | **Claude Code leads** |
|
| Agents | PASS: 65 agents | PASS: 12 agents | **Claude Code leads** |
|
||||||
| Commands | PASS: 84 commands | PASS: 35 commands | **Claude Code leads** |
|
| Commands | PASS: 85 commands | PASS: 35 commands | **Claude Code leads** |
|
||||||
| Skills | PASS: 262 skills | PASS: 37 skills | **Claude Code leads** |
|
| Skills | PASS: 263 skills | PASS: 37 skills | **Claude Code leads** |
|
||||||
| Hooks | PASS: 8 event types | PASS: 11 events | **OpenCode has more!** |
|
| Hooks | PASS: 8 event types | PASS: 11 events | **OpenCode has more!** |
|
||||||
| Rules | PASS: 29 rules | PASS: 13 instructions | **Claude Code leads** |
|
| Rules | PASS: 29 rules | PASS: 13 instructions | **Claude Code leads** |
|
||||||
| MCP Servers | PASS: 14 servers | PASS: Full | **Full parity** |
|
| MCP Servers | PASS: 14 servers | PASS: Full | **Full parity** |
|
||||||
@ -1668,9 +1668,9 @@ ECC is the **first plugin to maximize every major AI coding tool**. Here's how e
|
|||||||
|
|
||||||
| Feature | Claude Code | Cursor IDE | Codex CLI | OpenCode | GitHub Copilot |
|
| Feature | Claude Code | Cursor IDE | Codex CLI | OpenCode | GitHub Copilot |
|
||||||
|---------|-----------------------|------------|-----------|----------|----------------|
|
|---------|-----------------------|------------|-----------|----------|----------------|
|
||||||
| **Agents** | 64 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 | N/A |
|
| **Agents** | 65 | Shared (AGENTS.md) | Shared (AGENTS.md) | 12 | N/A |
|
||||||
| **Commands** | 84 | Shared | Instruction-based | 35 | 5 prompts |
|
| **Commands** | 85 | Shared | Instruction-based | 35 | 5 prompts |
|
||||||
| **Skills** | 262 | Shared | 10 (native format) | 37 | Via instructions |
|
| **Skills** | 263 | Shared | 10 (native format) | 37 | Via instructions |
|
||||||
| **Hook Events** | 8 types | 15 types | None yet | 11 types | None |
|
| **Hook Events** | 8 types | 15 types | None yet | 11 types | None |
|
||||||
| **Hook Scripts** | 20+ scripts | 16 scripts (DRY adapter) | N/A | Plugin hooks | N/A |
|
| **Hook Scripts** | 20+ scripts | 16 scripts (DRY adapter) | N/A | Plugin hooks | N/A |
|
||||||
| **Rules** | 34 (common + lang) | 34 (YAML frontmatter) | Instruction-based | 13 instructions | 1 always-on file |
|
| **Rules** | 34 (common + lang) | 34 (YAML frontmatter) | Instruction-based | 13 instructions | 1 always-on file |
|
||||||
|
|||||||
@ -164,7 +164,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
|
|||||||
/plugin list ecc@ecc
|
/plugin list ecc@ecc
|
||||||
```
|
```
|
||||||
|
|
||||||
**完成!** 你现在可以使用 64 个代理、262 个技能和 84 个命令。
|
**完成!** 你现在可以使用 65 个代理、263 个技能和 85 个命令。
|
||||||
|
|
||||||
### multi-* 命令需要额外配置
|
### multi-* 命令需要额外配置
|
||||||
|
|
||||||
|
|||||||
@ -103,7 +103,7 @@ You DO NOT refactor or rewrite code — you report findings only.
|
|||||||
|
|
||||||
### HIGH — State Management (Pinia)
|
### HIGH — State Management (Pinia)
|
||||||
|
|
||||||
- **Direct store property mutation without `$patch` or action**: Mutations outside actions lose devtools tracking and make state flow non-obvious.
|
- **Scattered complex store mutations outside actions or `$patch()`**: Pinia allows direct state writes, but multi-field business mutations should live in actions or grouped `$patch()` calls so devtools history and state flow stay understandable.
|
||||||
- **Storing non-serializable data in Pinia state**: Saved state (SSR hydration, devtools, local persistence) won't survive round-trip.
|
- **Storing non-serializable data in Pinia state**: Saved state (SSR hydration, devtools, local persistence) won't survive round-trip.
|
||||||
- **`mapState` / `mapActions` in Options API without proper typing**: Type inference breaks — prefer Composition API or declare full types.
|
- **`mapState` / `mapActions` in Options API without proper typing**: Type inference breaks — prefer Composition API or declare full types.
|
||||||
- **Store action without error boundary**: Async store actions should handle failures and not leave state inconsistent.
|
- **Store action without error boundary**: Async store actions should handle failures and not leave state inconsistent.
|
||||||
|
|||||||
@ -165,7 +165,6 @@ Recommendation: FAIL: Block merge until CRITICAL issue is fixed
|
|||||||
- Run tests to ensure component tests pass
|
- Run tests to ensure component tests pass
|
||||||
- Run `/vue-review` before merging Vue code
|
- Run `/vue-review` before merging Vue code
|
||||||
- Use `/code-review` for non-Vue-specific concerns on the same PR
|
- Use `/code-review` for non-Vue-specific concerns on the same PR
|
||||||
- Use `/vue-test` (if created) for Vue-specific test generation
|
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"totalCommands": 84,
|
"totalCommands": 85,
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"command": "aside",
|
"command": "aside",
|
||||||
@ -919,6 +919,23 @@
|
|||||||
"allAgents": [],
|
"allAgents": [],
|
||||||
"skills": [],
|
"skills": [],
|
||||||
"path": "commands/update-docs.md"
|
"path": "commands/update-docs.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "vue-review",
|
||||||
|
"description": "Comprehensive Vue.js code review for Composition API correctness, reactivity, composable patterns, template security, accessibility, and Vue-specific performance. Invokes the vue-reviewer agent (and typescript-reviewer alongside on .vue/.ts changes).",
|
||||||
|
"type": "testing",
|
||||||
|
"primaryAgents": [
|
||||||
|
"typescript-reviewer",
|
||||||
|
"vue-reviewer"
|
||||||
|
],
|
||||||
|
"allAgents": [
|
||||||
|
"typescript-reviewer",
|
||||||
|
"vue-reviewer"
|
||||||
|
],
|
||||||
|
"skills": [
|
||||||
|
"vue-patterns"
|
||||||
|
],
|
||||||
|
"path": "commands/vue-review.md"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"statistics": {
|
"statistics": {
|
||||||
@ -929,7 +946,7 @@
|
|||||||
"planning": 2,
|
"planning": 2,
|
||||||
"refactoring": 1,
|
"refactoring": 1,
|
||||||
"review": 9,
|
"review": 9,
|
||||||
"testing": 52
|
"testing": 53
|
||||||
},
|
},
|
||||||
"topAgents": [
|
"topAgents": [
|
||||||
{
|
{
|
||||||
@ -940,6 +957,10 @@
|
|||||||
"agent": "flutter-reviewer",
|
"agent": "flutter-reviewer",
|
||||||
"count": 2
|
"count": 2
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"agent": "typescript-reviewer",
|
||||||
|
"count": 2
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"agent": "cpp-build-resolver",
|
"agent": "cpp-build-resolver",
|
||||||
"count": 1
|
"count": 1
|
||||||
@ -967,10 +988,6 @@
|
|||||||
{
|
{
|
||||||
"agent": "planner",
|
"agent": "planner",
|
||||||
"count": 1
|
"count": 1
|
||||||
},
|
|
||||||
{
|
|
||||||
"agent": "python-reviewer",
|
|
||||||
"count": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"topSkills": [
|
"topSkills": [
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Everything Claude Code (ECC) — 智能体指令
|
# Everything Claude Code (ECC) — 智能体指令
|
||||||
|
|
||||||
这是一个**生产就绪的 AI 编码插件**,提供 64 个专业代理、262 项技能、84 条命令以及自动化钩子工作流,用于软件开发。
|
这是一个**生产就绪的 AI 编码插件**,提供 65 个专业代理、263 项技能、85 条命令以及自动化钩子工作流,用于软件开发。
|
||||||
|
|
||||||
**版本:** 2.0.0
|
**版本:** 2.0.0
|
||||||
|
|
||||||
@ -146,9 +146,9 @@
|
|||||||
## 项目结构
|
## 项目结构
|
||||||
|
|
||||||
```
|
```
|
||||||
agents/ — 64 个专业子代理
|
agents/ — 65 个专业子代理
|
||||||
skills/ — 262 个工作流技能和领域知识
|
skills/ — 263 个工作流技能和领域知识
|
||||||
commands/ — 84 个斜杠命令
|
commands/ — 85 个斜杠命令
|
||||||
hooks/ — 基于触发的自动化
|
hooks/ — 基于触发的自动化
|
||||||
rules/ — 始终遵循的指导方针(通用 + 每种语言)
|
rules/ — 始终遵循的指导方针(通用 + 每种语言)
|
||||||
scripts/ — 跨平台 Node.js 实用工具
|
scripts/ — 跨平台 Node.js 实用工具
|
||||||
|
|||||||
@ -228,7 +228,7 @@ Copy-Item -Recurse rules/typescript "$HOME/.claude/rules/"
|
|||||||
/plugin list ecc@ecc
|
/plugin list ecc@ecc
|
||||||
```
|
```
|
||||||
|
|
||||||
**搞定!** 你现在可以使用 64 个智能体、262 项技能和 84 个命令了。
|
**搞定!** 你现在可以使用 65 个智能体、263 项技能和 85 个命令了。
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
@ -1140,9 +1140,9 @@ opencode
|
|||||||
|
|
||||||
| 功能特性 | Claude Code | OpenCode | 状态 |
|
| 功能特性 | Claude Code | OpenCode | 状态 |
|
||||||
|---------|---------------|----------|--------|
|
|---------|---------------|----------|--------|
|
||||||
| 智能体 | PASS: 64 个 | PASS: 12 个 | **Claude Code 领先** |
|
| 智能体 | PASS: 65 个 | PASS: 12 个 | **Claude Code 领先** |
|
||||||
| 命令 | PASS: 84 个 | PASS: 35 个 | **Claude Code 领先** |
|
| 命令 | PASS: 85 个 | PASS: 35 个 | **Claude Code 领先** |
|
||||||
| 技能 | PASS: 262 项 | PASS: 37 项 | **Claude Code 领先** |
|
| 技能 | PASS: 263 项 | PASS: 37 项 | **Claude Code 领先** |
|
||||||
| 钩子 | PASS: 8 种事件类型 | PASS: 11 种事件 | **OpenCode 更多!** |
|
| 钩子 | PASS: 8 种事件类型 | PASS: 11 种事件 | **OpenCode 更多!** |
|
||||||
| 规则 | PASS: 29 条 | PASS: 13 条指令 | **Claude Code 领先** |
|
| 规则 | PASS: 29 条 | PASS: 13 条指令 | **Claude Code 领先** |
|
||||||
| MCP 服务器 | PASS: 14 个 | PASS: 完整 | **完全对等** |
|
| MCP 服务器 | PASS: 14 个 | PASS: 完整 | **完全对等** |
|
||||||
@ -1248,9 +1248,9 @@ ECC 是**第一个最大化利用每个主要 AI 编码工具的插件**。以
|
|||||||
|
|
||||||
| 功能特性 | Claude Code | Cursor IDE | Codex CLI | OpenCode |
|
| 功能特性 | Claude Code | Cursor IDE | Codex CLI | OpenCode |
|
||||||
|---------|-----------------------|------------|-----------|----------|
|
|---------|-----------------------|------------|-----------|----------|
|
||||||
| **智能体** | 64 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |
|
| **智能体** | 65 | 共享 (AGENTS.md) | 共享 (AGENTS.md) | 12 |
|
||||||
| **命令** | 84 | 共享 | 基于指令 | 35 |
|
| **命令** | 85 | 共享 | 基于指令 | 35 |
|
||||||
| **技能** | 262 | 共享 | 10 (原生格式) | 37 |
|
| **技能** | 263 | 共享 | 10 (原生格式) | 37 |
|
||||||
| **钩子事件** | 8 种类型 | 15 种类型 | 暂无 | 11 种类型 |
|
| **钩子事件** | 8 种类型 | 15 种类型 | 暂无 | 11 种类型 |
|
||||||
| **钩子脚本** | 20+ 个脚本 | 16 个脚本 (DRY 适配器) | N/A | 插件钩子 |
|
| **钩子脚本** | 20+ 个脚本 | 16 个脚本 (DRY 适配器) | N/A | 插件钩子 |
|
||||||
| **规则** | 34 (通用 + 语言) | 34 (YAML 前页) | 基于指令 | 13 条指令 |
|
| **规则** | 34 (通用 + 语言) | 34 (YAML 前页) | 基于指令 | 13 条指令 |
|
||||||
|
|||||||
@ -97,6 +97,14 @@
|
|||||||
"framework-language"
|
"framework-language"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "framework:vue",
|
||||||
|
"family": "framework",
|
||||||
|
"description": "Vue.js, Nuxt, Pinia, and Vue Router engineering guidance. Currently resolves through the shared framework-language module.",
|
||||||
|
"modules": [
|
||||||
|
"framework-language"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "framework:nextjs",
|
"id": "framework:nextjs",
|
||||||
"family": "framework",
|
"family": "framework",
|
||||||
@ -510,6 +518,14 @@
|
|||||||
"framework-language"
|
"framework-language"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "skill:vue-patterns",
|
||||||
|
"family": "skill",
|
||||||
|
"description": "Vue.js 3 Composition API, reactivity, Pinia, Vue Router, and Nuxt SSR patterns.",
|
||||||
|
"modules": [
|
||||||
|
"framework-language"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "skill:backend-patterns",
|
"id": "skill:backend-patterns",
|
||||||
"family": "skill",
|
"family": "skill",
|
||||||
|
|||||||
@ -183,7 +183,8 @@
|
|||||||
"skills/springboot-patterns",
|
"skills/springboot-patterns",
|
||||||
"skills/springboot-tdd",
|
"skills/springboot-tdd",
|
||||||
"skills/springboot-verification",
|
"skills/springboot-verification",
|
||||||
"skills/ui-to-vue"
|
"skills/ui-to-vue",
|
||||||
|
"skills/vue-patterns"
|
||||||
],
|
],
|
||||||
"targets": [
|
"targets": [
|
||||||
"claude",
|
"claude",
|
||||||
|
|||||||
@ -307,6 +307,7 @@
|
|||||||
"skills/video-editing/",
|
"skills/video-editing/",
|
||||||
"skills/videodb/",
|
"skills/videodb/",
|
||||||
"skills/visa-doc-translate/",
|
"skills/visa-doc-translate/",
|
||||||
|
"skills/vue-patterns/",
|
||||||
"skills/windows-desktop-e2e/",
|
"skills/windows-desktop-e2e/",
|
||||||
"skills/workspace-surface-audit/",
|
"skills/workspace-surface-audit/",
|
||||||
"skills/x-api/",
|
"skills/x-api/",
|
||||||
|
|||||||
@ -75,7 +75,7 @@ watch(() => count, (newVal) => { ... });
|
|||||||
When passing a destructured prop to a composable that needs reactivity, wrap in a getter and use `toValue()` inside the composable:
|
When passing a destructured prop to a composable that needs reactivity, wrap in a getter and use `toValue()` inside the composable:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
useDynamicCount(() => count); // ✅ preserves reactivity
|
useDynamicCount(() => count); // preserves reactivity
|
||||||
```
|
```
|
||||||
|
|
||||||
### Replacing reactive() Objects
|
### Replacing reactive() Objects
|
||||||
@ -132,7 +132,7 @@ const fullName = computed({
|
|||||||
|
|
||||||
// WRONG: side effect in computed
|
// WRONG: side effect in computed
|
||||||
const displayName = computed(() => {
|
const displayName = computed(() => {
|
||||||
analytics.track("name-computed"); // ❌ side effect
|
analytics.track("name-computed"); // side effect
|
||||||
return user.value.name;
|
return user.value.name;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -164,23 +164,19 @@ watchEffect(() => {
|
|||||||
## Watcher Source Pitfalls
|
## Watcher Source Pitfalls
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
// WRONG: watching a ref object (never changes)
|
// CORRECT: watching a ref tracks its value
|
||||||
const u = ref({ name: "Alice" });
|
const u = ref({ name: "Alice" });
|
||||||
watch(u, (val) => {}); // ❌ watches the ref wrapper, not the value
|
watch(u, (val) => {});
|
||||||
|
|
||||||
// CORRECT: getter returning .value
|
// ALSO CORRECT: getter returning .value
|
||||||
watch(() => u.value, (val) => {});
|
watch(() => u.value, (val) => {});
|
||||||
|
|
||||||
// ALSO WRONG: reactive getter that doesn't track
|
|
||||||
watch(() => state.name, (val) => {}); // ❌ val is snapshot at setup
|
|
||||||
|
|
||||||
// CORRECT: getter that accesses property on reactive object
|
// CORRECT: getter that accesses property on reactive object
|
||||||
watch(() => state.name, (val) => {}); // ✅ .name access inside getter is tracked
|
watch(() => state.name, (val) => {}); // .name access inside getter is tracked
|
||||||
// Wait — careful: `() => state.name` DOES track correctly because the getter
|
// The getter is re-evaluated because it accesses `.name` on the reactive proxy.
|
||||||
// accesses `.name` on the reactive proxy. The getter is re-evaluated by Vue.
|
|
||||||
|
|
||||||
// ACTUALLY WRONG case: direct reactive property
|
// WRONG: direct reactive property
|
||||||
watch(state.name, ...); // ❌ state.name evaluates to a primitive, not trackable
|
watch(state.name, ...); // state.name evaluates to a primitive, not trackable
|
||||||
|
|
||||||
// CORRECT: getter returning reactive property
|
// CORRECT: getter returning reactive property
|
||||||
watch(() => state.name, (newName) => { ... });
|
watch(() => state.name, (newName) => { ... });
|
||||||
@ -190,7 +186,7 @@ watch(() => state.name, (newName) => { ... });
|
|||||||
|
|
||||||
Every watcher that creates subscriptions, intervals, or fetch requests must clean up.
|
Every watcher that creates subscriptions, intervals, or fetch requests must clean up.
|
||||||
|
|
||||||
**Vue 3.5+**: Use `onWatcherCleanup()` (globally importable from `vue`) for watcher-side-effect cleanup:
|
**Vue 3.5+**: Use `onWatcherCleanup()` (globally importable from `vue`) for watcher-side-effect cleanup. It must be called synchronously inside the watcher callback:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { watch, onWatcherCleanup } from "vue";
|
import { watch, onWatcherCleanup } from "vue";
|
||||||
@ -319,7 +315,7 @@ Never initialize state, start timers, or subscribe to external systems in the mo
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
// WRONG: module scope side effect
|
// WRONG: module scope side effect
|
||||||
const globalCount = ref(0); // ❌ shared across all components
|
const globalCount = ref(0); // FAIL shared across all components
|
||||||
setInterval(() => globalCount.value++, 1000);
|
setInterval(() => globalCount.value++, 1000);
|
||||||
|
|
||||||
export function useGlobalCount() {
|
export function useGlobalCount() {
|
||||||
@ -342,7 +338,7 @@ Use `shallowRef()` for large immutable data structures that are replaced as a wh
|
|||||||
```ts
|
```ts
|
||||||
const items = shallowRef<Item[]>([]);
|
const items = shallowRef<Item[]>([]);
|
||||||
// items.value = await fetchItems(); // replacement works
|
// items.value = await fetchItems(); // replacement works
|
||||||
// items.value[0].name = "new"; // ❌ inner mutations are NOT reactive
|
// items.value[0].name = "new"; // FAIL inner mutations are NOT reactive
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `shallowReactive()` when only top-level properties should be reactive.
|
Use `shallowReactive()` when only top-level properties should be reactive.
|
||||||
|
|||||||
@ -317,7 +317,7 @@ Use `<Teleport>` for modals, tooltips, notifications — content that must escap
|
|||||||
|
|
||||||
```vue
|
```vue
|
||||||
<!-- defer: target can appear after the Teleport in the DOM -->
|
<!-- defer: target can appear after the Teleport in the DOM -->
|
||||||
<Teleport defer target="#container">
|
<Teleport defer to="#container">
|
||||||
<p>Teleported content</p>
|
<p>Teleported content</p>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<div id="container"></div>
|
<div id="container"></div>
|
||||||
|
|||||||
@ -83,7 +83,7 @@ app.directive("render-html", (el, binding) => {
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
// CRITICAL: secret leaked to client bundle (Vite)
|
// CRITICAL: secret leaked to client bundle (Vite)
|
||||||
const apiKey = import.meta.env.VITE_STRIPE_SECRET; // ❌ VITE_ prefix = public
|
const apiKey = import.meta.env.VITE_STRIPE_SECRET; // FAIL VITE_ prefix = public
|
||||||
|
|
||||||
// CORRECT: server-side only
|
// CORRECT: server-side only
|
||||||
// vite.config.ts — never pass VITE_ prefixed secrets
|
// vite.config.ts — never pass VITE_ prefixed secrets
|
||||||
@ -158,7 +158,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
// CRITICAL: session tokens in localStorage
|
// CRITICAL: session tokens in localStorage
|
||||||
localStorage.setItem("token", jwt); // ❌ any XSS can read this
|
localStorage.setItem("token", jwt); // FAIL any XSS can read this
|
||||||
|
|
||||||
// CORRECT: httpOnly cookie set by server
|
// CORRECT: httpOnly cookie set by server
|
||||||
// Client never touches the token directly.
|
// Client never touches the token directly.
|
||||||
|
|||||||
@ -201,7 +201,7 @@ export const useCartStore = defineStore("cart", () => {
|
|||||||
```
|
```
|
||||||
|
|
||||||
- Use Setup Store syntax (not Options Store).
|
- Use Setup Store syntax (not Options Store).
|
||||||
- Actions: only place to mutate state.
|
- Prefer actions for business-level mutations and `$patch()` for grouped updates.
|
||||||
- Every async action: handle loading + success + error.
|
- Every async action: handle loading + success + error.
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -385,7 +385,7 @@ const { count = 0, msg = "hello" } = defineProps<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
// Limitation: cannot watch destructured prop directly
|
// Limitation: cannot watch destructured prop directly
|
||||||
watch(() => count, (newVal) => { ... }); // ✅ getter required
|
watch(() => count, (newVal) => { ... }); // PASS getter required
|
||||||
```
|
```
|
||||||
|
|
||||||
### `useTemplateRef()`
|
### `useTemplateRef()`
|
||||||
@ -402,7 +402,7 @@ Supports dynamic ref IDs: `useTemplateRef(dynamicRefId)`.
|
|||||||
|
|
||||||
### `onWatcherCleanup()`
|
### `onWatcherCleanup()`
|
||||||
|
|
||||||
Globally importable watcher cleanup API (Vue 3.5+):
|
Globally importable watcher cleanup API (Vue 3.5+). It must be called synchronously inside the watcher callback:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { watch, onWatcherCleanup } from "vue";
|
import { watch, onWatcherCleanup } from "vue";
|
||||||
@ -428,7 +428,7 @@ const id = useId();
|
|||||||
`<Teleport defer>` allows teleporting to targets rendered in the same cycle:
|
`<Teleport defer>` allows teleporting to targets rendered in the same cycle:
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<Teleport defer target="#container">Content</Teleport>
|
<Teleport defer to="#container">Content</Teleport>
|
||||||
<div id="container"></div>
|
<div id="container"></div>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user