Vue
November 24, 2024
Vue 3 da watch methodi
watch() metodi reaktiv ma'lumotlardagi o'zgarishlarni kuzatish va ularga javob qaytarish uchun ishlatiladi. Bu metod quyidagi asosiy xususiyatlarga ega:
Asosiy xususiyatlari
- Side Effects: Reactive data o'zgarganda side effect'larni bajarish imkonini beradi
- Async Operations: Async operatsiyalarni bajarish imkoniyati
- Control: Watching boshlanishi va to'xtatilishini nazorat qilish
- Deep watching: Obyektlarni chuqur kuzatish imkoniyati
Basic Usage
import { ref, watch } from 'vue'
const searchQuery = ref('')
const searchResults = ref([])
// Basic watcher
watch(searchQuery, async (newQuery, oldQuery) => {
if (newQuery.trim()) {
const results = await fetchSearchResults(newQuery)
searchResults.value = results
} else {
searchResults.value = []
}
})Multiple Sources
Bir nechta source'larni kuzatish mumkin:
const firstName = ref('John')
const lastName = ref('Doe')
watch([firstName, lastName], ([newFirst, newLast], [oldFirst, oldLast]) => {
console.log(`Name changed from ${oldFirst} ${oldLast} to ${newFirst} ${newLast}`)
})Deep Watching
Obyekt ichidagi o'zgarishlarni ham kuzatish:
const user = reactive({
name: 'John',
profile: {
age: 25,
city: 'Tashkent'
}
})
// Deep watcher
watch(user, (newValue, oldValue) => {
console.log('User data changed:', newValue)
}, { deep: true })Immediate Watching
Watcher ni darhol ishga tushirish:
const todoId = ref(1)
const todoData = ref(null)
watch(todoId, async (newId) => {
todoData.value = await fetchTodo(newId)
}, { immediate: true })Watch vs watchEffect
Vue 3 da ikkita watching mexanizmi mavjud:
watch
- Aniq source va callback bilan ishlaydi
- Old va new qiymatlarni taqdim etadi
- Watching qachon ishga tushishini nazorat qilish mumkin
const counter = ref(0)
watch(counter, (newValue, oldValue) => {
console.log(`Counter changed from ${oldValue} to ${newValue}`)
})watchEffect
- Avtomatik ravishda dependency'larni kuzatadi
- Callback ichida ishlatilgan har qanday reactive value o'zgarganda ishga tushadi
- Darhol ishga tushadi
const todos = ref([])
const error = ref(null)
watchEffect(async () => {
try {
todos.value = await fetchTodos()
} catch (e) {
error.value = e
}
})Stop Watching
const stop = watch(source, callback) // Kerak bo'lganda stop()
Best Practices
watch(id, async (newId, oldId, onCleanup) => {
const { response, cancel } = doAsyncWork(newId)
// Agar yangi watcher ishga tushsa, oldingi requestni bekor qilish
onCleanup(() => cancel())
data.value = await response
})watch(source, async (value) => {
try {
await someAsyncOperation()
} catch (error) {
console.error('Error in watcher:', error)
}
})import { debounce } from 'lodash'
const debouncedWatch = watch(searchInput, debounce((value) => {
// Search logic here
}, 300))
Anti-patterns va Ogohlantirishlar
1. Computed property o'rniga watch ishlatish
// ❌ Yomon
watch([firstName, lastName], ([first, last]) => {
fullName.value = `${first} ${last}`
})
// ✅ Yaxshi
const fullName = computed(() => `${firstName.value} ${lastName.value}`)- Performance: Watch har doim callback funksiyani to'liq bajaradi, computed esa keshlanadi va faqat dependency o'zgargandagina qayta hisoblanadi
- Code readability: Computed aniq ko'rsatadiki bu yangi value hisoblanmoqda. Watch esa side-effect uchun mo'ljallangan
- Debugging: Computed bilan value qayerdan kelayotganini kuzatish osonroq
- Testing: Computed propertylarni test qilish osonroq chunki ular pure function
2. Bir watcher ichida ko'p vazifalarni bajarish
// ❌ Yomon
watch(user, () => {
updateProfile()
sendAnalytics()
refreshUI()
loadRelatedData()
})
// ✅ Yaxshi - Alohida watcherlar
watch(user, updateProfile)
watch(user, sendAnalytics)
watch(user, refreshUI)
watch(user, loadRelatedData)- Maintainability: Har bir watcher alohida mas'uliyatga ega bo'lishi kerak (Single Responsibility Principle)
- Error handling: Bitta funksiyada xato chiqsa, boshqa funksiyalar ham ishlamay qoladi
- Testing: Ko'p vazifali watcherni test qilish murakkab
- Debug qilish: Xato qaysi operatsiyada yuz berganini aniqlash qiyin
3. Watch ichida reactive data o'zgartirish
// ❌ Yomon
watch(count, (newCount) => {
anotherCount.value = newCount * 2
})
// ✅ Yaxshi
const anotherCount = computed(() => count.value * 2)- Infinite loop xavfi: Agar watched value watcherni ichida o'zgartirilsa, infinite loop yuzaga kelishi mumkin
- State management murakkabligi: Reactive datani bir necha joyda o'zgartirish debug qilishni qiyinlashtiradi
- Vue'ning reaktivlik tizimidan noto'g'ri foydalanish: Bu vazifa computed property uchun mo'ljallangan
4. Watcherda og'ir operatsiyalarni to'g'ridan-to'g'ri bajarish
// ❌ Yomon
watch(searchQuery, (query) => {
const results = heavyComputation(query)
searchResults.value = results
})
// ✅ Yaxshi
watch(searchQuery, debounce(async (query) => {
const results = await heavyComputation(query)
searchResults.value = results
}, 300))- Performance: Har bir o'zgarishda og'ir hisob-kitoblar UI ni sekinlashtiradi
- User Experience: Foydalanuvchi kiritayotgan vaqtda ham hisob-kitoblar amalga oshiriladi
- Resource usage: Keraksiz hisob-kitoblar tizim resurslarini behuda sarflaydi
5. Deep watching ni keraksiz ishlatish
// ❌ Yomon
watch(complexObject, (newVal) => {
// Something with newVal
}, { deep: true })
// ✅ Yaxshi - Faqat kerakli propertyni kuzatish
watch(() => complexObject.specificProperty, (newVal) => {
// Something with newVal
})- Performance: Deep watching katta obyektlar uchun sezilarli performance yo'qotishga olib keladi
- Unnecessary updates: Keraksiz propertylar o'zgarganda ham watcher ishga tushadi
- Memory usage: Vue har bir property uchun reactive wrapper yaratishi kerak bo'ladi
6. watchEffect ichida async operatsiyalarni noto'g'ri boshqarish
// ❌ Yomon
watchEffect(async () => {
const data = await fetchData()
results.value = data
})
// ✅ Yaxshi
watchEffect((onCleanup) => {
const controller = new AbortController()
onCleanup(() => controller.abort())
fetchData({ signal: controller.signal })
.then(data => {
results.value = data
})
})- Race conditions: Oldingi request tugatilmasdan yangi request boshlanishi mumkin
- Memory leaks: Cleanup funksiyasisiz eskii requestlar to'planib qolishi mumkin
- State inconsistency: Natijalar noto'g'ri tartibda kelishi mumkin
Best Practice Recommendations
- Watch o'rniga computed ishlatish mumkin bo'lgan holatlarni aniqlang
- Agar yangi value hisoblash kerak bo'lsa - computed ishlating
- Agar side-effect (API call, DOM manipulation) kerak bo'lsa - watch ishlating
- Watcherlarni kichik va aniq vazifalar uchun ajrating
- Har bir watcher bitta vazifani bajarsin
- Vazifalar bir-biriga bog'liq bo'lsa, alohida composable funksiya yarating
- Async operatsiyalar uchun cleanup ishlatishni unutmang
- Race conditionlardan qochish uchun
- Memory leaklarni oldini olish uchun
- Network requestlarni to'g'ri boshqarish uchun
- Watch va watchEffect ni to'g'ri tanlang
- Watch - aniq dependency va old/new value kerak bo'lganda
- watchEffect - dependency avtomatik aniqlanishi kerak bo'lganda
- Performance optimizatsiyasi
Hozircha shu, keyingi postlarda ko'rishguncha. Stay tuned...
@peaceofcode