加 immediate: true 可使 watch 回调在组件创建完成时立即执行一次,适用于初始化依赖 props、ref 初值或对象配置的场景,需作为 options 对象属性与 deep 等配合使用,首次 oldValue 为 undefined。
加 immediate: true 就行——它让 watch 回调在组件创建完成、监听器挂载好的那一刻,立刻用当前值执行一次,而不是等数据“变”了才动。
以下情况不加 immediate,逻辑就跑不通:
props.productId),子组件需要一上来就根据它请求详情ref 初始化了一个变量,且赋了初值(如 const searchKey = ref('vue')),你希望页面还没渲染完就先走一遍搜索逻辑immediate 不是独立参数,必须作为 watch 的第三个参数(options 对象)里的一个属性,和 deep、flush 等并列。
✅ 正确写法:
const userId = ref('U1001')watch(() => userId.value, (newId, oldId) => { console.log('ID 变了或刚进来', newId)}, { immediate: true })
❌ 错误写法(像 Vue2 那样把 immediate 放错位置):
// 这样 immediate 不生效watch( () => userId.value, { immediate: true }, // 错:把配置当成了 handler (newId) => { /* ... */ })
很多初始化数据是对象或数组,比如 props.config 或 ref({ theme: 'dark', lang: 'zh' })。这时往往要同时开 deep: true 和 immediate: true:
deep: true → 监听到对象内部任意属性变化(如 config.theme 改了)immediate: true → 第一次拿到完整 config 时就立刻应用主题、语言等设置示例:
watch(() => props.config, (newConfig) => { applyTheme(newConfig.theme) setLanguage(newConfig.lang)}, { immediate: true, deep: true })
首次执行时,oldValue 一定是 undefined —— 因为还没“上一次”的值。所以判断逻辑别踩坑:
if (newVal && newVal.id) { ... }
if (oldVal !== newVal) { ... }(首次永远为 true,可能引发误判)另外,确保初始值是合法对象/数组,别是 null 或 undefined,否则开 deep 会报错“Cannot convert undefined or null to object”。