Ba điểm hay vướng khi watch dữ liệu dạng object:
1. deep. watch một ref chứa object chỉ chạy khi thay cả object (obj.value = {...}). Đổi thuộc tính bên trong thì không kích hoạt — trừ khi bật { deep: true }. Riêng khi nguồn là chính một object reactive, Vue tự deep.
watch(user, cb) // fires only when user.value is replaced
watch(user, cb, { deep: true }) // fires on nested changes too
watch(() => user.value.name, cb) // better: watch the exact field2. oldValue === newValue. Với deep watcher trên object, callback nhận cùng một tham chiếu cho cả cũ và mới, vì object bị mutate tại chỗ. Cần giá trị cũ thật thì watch một getter trả về giá trị nguyên thuỷ, hoặc tự copy trước.
3. flush. Mặc định pre — callback chạy trước khi component re-render, nên DOM còn là trạng thái cũ. Cần đọc DOM sau cập nhật thì dùng { flush: 'post' } (tương đương gọi nextTick bên trong). flush: 'sync' chạy ngay lập tức, không gộp batch, chỉ dùng cho trường hợp đặc biệt vì dễ gây gọi lặp.
deep: true trên cây object lớn có chi phí duyệt toàn bộ — ưu tiên watch đúng field cần thiết.