Logical Reuse and Performance Optimization
After completing the routing and login logic, as the project scales, we will find that some logic (such as accessing local data, popping up notifications) appears repeatedly across multiple pages. At the same time, if the task list reaches thousands of items, the page may lag.
In this phase, we will usethe in-depth application of the Composition APIto solve code reuse and performance bottleneck issues.
Logic Reuse: Custom Composables (Hooks)
Composables are the essence of Vue 3; they allow us to extract logic (State + Actions) into independent functions.
useLocalStorage: Data Persistence Logic Extraction
No more manually writing in every Store or componentlocalStorage.getItem。
Example
import { ref, watch } from 'vue';
export function useLocalStorage(key, defaultValue = null) {
// 1. Initialize data
const storedValue = localStorage.getItem(key);
const data = ref(storedValue ? JSON.parse(storedValue) : defaultValue);
// 2. Listen for changes and sync automatically
watch(data, (newValue) => {
localStorage.setItem(key, JSON.stringify(newValue));
}, { deep: true });
return data;
}
useNotification: Common UI Logic Extraction
Implement a simple notification prompt feature.
Example
import { ref } from 'vue';
export function useNotification() {
const message = ref('');
const isVisible = ref(false);
const notify = (msg, duration = 2000) => {
message.value = msg;
isVisible.value = true;
setTimeout(() => {
isVisible.value = false;
}, duration);
};
return { message, isVisible, notify };
}
Performance Optimization: Handling Large Data Volumes and High-Frequency Rendering
When your TaskHub grows from managing 10 tasks to managing 1000 tasks, Vue's default "deep reactivity" will bring computational pressure.
shallowRefandmarkRaw
Vue's defaultrefis recursively reactive (i.e., every property inside the object is proxied).
shallowRef: Only listen to.valuethe change of the reference, not the changes of the object's internal properties.
- Scenario: When you fetch a large read-only list of task history from the backend.
markRaw: Mark an object to make itneverbe converted to reactive.
- Scenario: Some complex third-party library instances (such as ECharts chart instances, map instances) may cause errors or be extremely performance-intensive if wrapped as reactive.
// 性能优化示例
import { shallowRef, markRaw } from 'vue';
// 假设这是一万条历史归档数据
const archiveTasks = shallowRef([]);
const loadArchive = (data) => {
// 仅在赋值时触发一次响应式更新,内部属性修改不触发
archiveTasks.value = data;
};
v-onceandv-memo(Directive-level Optimization)
v-once: Static content is rendered only once
If a task no longer changes after rendering (e.g., the task creation time), usev-once。
<span v-once>创建于: {{ task.createdAt }}</span>
- Principle: Vue will skip subsequent update checks for that node after rendering.
v-memo: On-demand update (Vue 3.2+)
This is the most powerful directive for optimizing long lists. It accepts an array of dependencies; only when the values in the array change, the node and its child nodes will re-render.
<li v-for="task in tasks" :key="task.id" v-memo="[task.isCompleted, task.title]">
{{ task.title }} - {{ task.isCompleted }}
</li>
When should you optimize?
| Solution | Problems solved | Recommended scenarios |
|---|---|---|
| Composables | Code duplication, scattered logic | Cross-component shared logic (e.g., login checks, theme switching) |
| shallowRef | Memory overhead caused by deep proxying of large objects | When list data volume > 1000 and only needs to be replaced wholesale |
| v-memo | Frequent virtual DOM diffing of long lists | Complexv-forlists, and only a few properties change per item |
Integrating into the Previous Project
You can try toTaskItem.vueapply inv-memo:
<template>
<li v-memo="[task.id, task.isCompleted]" class="...">
...
</li>
</template>
Now your project is not only logically clear (Composables), but also has strong performance.
Other Extensions