Vue
November 24
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