Core Principles
- Keep state predictable: single source of truth, derive everything else.
- Make data flow explicit: most of the time, props down, events up.
- Avoid giant components: split large components into smaller (but also moderate), more focused child components.
- Avoid unnecessary re-renders: use computed properties and watchers appropriately.
- Readability is crucial: write clear, self-documenting code.
Tech Stack
The versions in the tech stack absolutely matter, as they determine that you use the latest and most reliable APIs, and prohibit the use of deprecated or outdated APIs. For example, Vue 3.5 introduced useTemplateRef, which can automatically infer the types of template refs, and should be preferred.
Remember,absolutely never write code based on your past training data, the specific tech stack is as follows:
- Vue 3.5(Composition API) + Single-File Components + setup syntax.
- TypeScript 6.x。
- Latest version of the SCSS preprocessor.
Vue 3 Component Guidelines
Avoid Giant Components
Under no circumstances are giant components allowed; this is definitely not a functional defect, but a problem in component design.
When the line count of a single component reaches 500 - 800 lines, it can basically be judged that this is a giant component, or there is a trend toward becoming a giant component.
Why giant components are bad:
- Because human short-term memory is limited, developers can easily lose context when scrolling through code, leading to difficulty in understanding.
- Logic bloat, violating the single responsibility principle.
- It leads to structural complexity, with JSX / Template nesting too deeply
- Difficult to maintain, poor reusability. Giant components are usually highly coupled and difficult to split and reuse.
- It leads to performance issues, making it impossible to update Vue templates locally more efficiently, greatly increasing the cost of re-rendering.
Keep the following practices:
- Separate UI. Split purely presentational stateless components and components with their own specific state and logic, keeping component responsibilities single.
- Use composable functions. Encapsulate a set of related logic into reusable functions (useXxx()), including state management, side effects, and event handling.
- Utility encapsulation. For logic functions and helper code used multiple times, and that are stateless and side-effect free, perform utility encapsulation.
- Lift state. For state shared by multiple components, lift it to their nearest common ancestor component for management, avoiding prop drilling, for example by using Vue's provide/inject or a Pinia store.
Apply objective split trigger conditions. If any of the following conditions is met, split the component:
- It simultaneously has orchestration/state logic and a large amount of presentational markup for multiple parts.
- It contains more than 3 different UI parts (for example: form, filters, list, footer/status).
- There are template blocks or reusable parts that are used repeatedly (such as item rows, cards, list entries).
Entry/root and route view rules:
- Keep entry/root and route view components lean: app shell/layout, provider connections, and feature composition.
- When a feature contains standalone parts, do not put the full feature implementation in the entry/root/view component.
Code readability
- Clear naming. Variables, functions, components, and files should have descriptive names that accurately reflect their purpose and behavior.
- Consistent style. Follow a consistent code style and conventions.
- Avoid over-abstraction. Over-abstraction increases the difficulty of understanding and debugging; keep code simple and direct.
- Use comments. Add comments for complex logic or unintuitive parts, but avoid excessive comments; code should be as self-explanatory as possible.
Ensure performance
-
Use async components. Use async components to lazy-load heavyweight, infrequently used, on-demand components.
-
Avoid frequently re-rendering the entire template. Do not allow high-frequency triggered events, animations, or timers to cause the entire template to re-render. For example, when using the mouse to drag a slider, you may only want to update the slider's UI state, but this causes the entire page to re-render. Even if other parts of the page appear unchanged, Vue will still re-execute the entire template render function, causing performance issues.
-
Bind key for list rendering。
-
Reduce reactivity system overhead。
- Avoid defining every variable as a reactive object; judge based on actual business needs.
- For properties that do not need to be reactive, use
shallowReforshallowReactive。
-
Prevent memory leaks。
- Clean up timers, event listeners, and other side effects when the component is destroyed.
- Use
onUnmounted、onBeforeUnmount、onScopeDisposeand other lifecycle hooks to perform cleanup logic.
-
Do not perform intermediate copy operations on reactive data. Keep reactive data passed directly between components. Except for special needs (for example, needing to retain initial data for reset, or genuinely needing a copied instance), avoid data copy operations. This operation requires an additional data synchronization mechanism, which is not only troublesome and reduces component maintainability, but also reduces performance.
Preferences
- Use
useTemplateRefinstead ofrefto obtain template refs.