963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
3.6 KiB
3.6 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Use immediate Option Instead of Duplicate Initial Call | LOW | Duplicate code for initial call and watch callback reduces maintainability | efficiency |
|
Use immediate Option Instead of Duplicate Initial Call
Impact: LOW - Calling a function manually at setup and also in a watcher leads to duplicate code. The immediate: true option runs the watcher callback immediately with the current value, combining both behaviors.
Task Checklist
- Use
{ immediate: true }instead of calling handler in onMounted/created - Consider
watchEffectas an alternative (always runs immediately) - Remember immediate callback receives
undefinedas oldValue on first run
Incorrect:
<script setup>
import { ref, watch, onMounted } from 'vue';
const userId = ref(1);
const userData = ref(null);
// BAD: Duplicate calls - once in onMounted, once in watch
async function loadUser(id) {
const response = await fetch(`/api/users/${id}`);
userData.value = await response.json();
}
onMounted(() => {
loadUser(userId.value); // Initial call
});
watch(userId, (newId) => {
loadUser(newId); // On change
});
</script>
// Options API - BAD: Duplicate in created and watch
export default {
data() {
return { userId: 1, userData: null };
},
created() {
this.loadUser(); // Initial call
},
watch: {
userId() {
this.loadUser(); // On change - duplicate!
},
},
methods: {
async loadUser() {
const response = await fetch(`/api/users/${this.userId}`);
this.userData = await response.json();
},
},
};
Correct:
<script setup>
import { ref, watch } from 'vue';
const userId = ref(1);
const userData = ref(null);
// GOOD: Single watch with immediate runs on mount and on change
watch(
userId,
async (newId) => {
const response = await fetch(`/api/users/${newId}`);
userData.value = await response.json();
},
{ immediate: true },
);
</script>
// Options API - GOOD: Using immediate option
export default {
data() {
return { userId: 1, userData: null };
},
watch: {
userId: {
async handler(newId) {
const response = await fetch(`/api/users/${newId}`);
this.userData = await response.json();
},
immediate: true,
},
},
};
Alternative: watchEffect
<script setup>
import { ref, watchEffect } from 'vue';
const userId = ref(1);
const userData = ref(null);
// watchEffect always runs immediately - no option needed
watchEffect(async () => {
const response = await fetch(`/api/users/${userId.value}`);
userData.value = await response.json();
});
</script>
Handling oldValue on Initial Run
<script setup>
import { ref, watch } from 'vue';
const count = ref(0);
watch(
count,
(newVal, oldVal) => {
// On first run with immediate: true
// oldVal is undefined
if (oldVal === undefined) {
console.log('Initial run, count is:', newVal);
} else {
console.log(`Count changed from ${oldVal} to ${newVal}`);
}
},
{ immediate: true },
);
</script>
One-Time Watch with once Option
<script setup>
import { ref, watch } from 'vue';
const data = ref(null);
// Run only once when data becomes available
watch(
data,
(value) => {
if (value) {
initializeWithData(value);
// Watcher automatically stops after this
}
},
{ once: true },
);
</script>