Vue3 修改 ref的值,不触发watchEffect的原因

const myRef = ref(name: ‘jinD’)

修改 myRef.value.xxx时,不触发watchEffect的原因在于,触发trigger传入的对象是否相同,在 watchEffect 里面访问 myRef.value 时,此时 track的target 是refCompImpl实例,也就是ref

但是修改值时,是通过 myRef.value.xxx = newValue, 不是给 myRef.value = {}设置新值,触发的trigger是在 proxy 的 getter里面(ref 都给传入的对象调用了reative, 也就是把传入的对象转为了proxy),此时trigger的target = {name: ‘xxx’}, 和之前track的 target不一致,没有获取到对应的effect(一个effect就是一个依赖,这里可以理解为watchEffect传入的cb), 所以不会导致 watchEffect 传入的cb重新执行

代码解析:

import { defineComponent, computed, ref, watchEffect } from 'vue'

const obj = {
  name: 'jinD',
}
export default defineComponent({
  name: 'app',

  setup() {
    const myRef = ref({ name: 'jinD' })

    watchEffect(() => {
      console.log('watchEffect 执行')

      console.log(myRef.value) // 这里收集的依赖时 target = refCompImpL
    })

    // debugger
    // myRef.value = { name: 'ding123' }  这样才会导致 watchEffect 重新执行

    myRef.value.name = 'ding1' // 修改的是 name的值,没有修改ref.value的值,不会触发ref的trigger,触发的trigger是在 myRef.value这个proxy上面的,修改 myRef.value.name 时,触发的trigger是在 proxy的setter里面的,此时触发trigger ,target = {name: 'jinD'}, 但是没有给{name: 'jinD'} 收集依赖,所以不会触发 watchEffect 的 cb

    return () => {
      
      return <p>123</p>
    }
  },
})

### Vue3 中 `watch` 和 `watchEffect` 的区别及使用场景 #### 工作机制对比 在 Vue 3 中,`watch` 和 `watchEffect` 都是用来监听响应式数据的变化并触发回调函数的工具。然而,两者的实现方式和适用场景存在显著差异。 - **`watch`**: 它允许开发者显式指定要监听的目标(可以是一个或多个响应式属性),只有当这些目标发生变化时才会触发回调函数[^1]。 - **`watchEffect`**: 需要手动声明依赖关系,它会自动追踪模板中的所有响应式变量,并在其发生改变时重新执行整个回调函数[^2]。 #### 参数设置与灵活性 对于参数配置而言: - 使用 `watch` 可以为用户提供更多控制选项,比如可以通过 `{ immediate: true }` 来决定是否立刻调用一次监听器;还可以通过自定义调度策略来调整如何以及何时应用更改到 DOM 上等细节。 - 而相比之下,虽然 `watchEffect` 提供了一个更简单的 API 表面来看更加便捷高效,但它缺乏像前者那样的精细调节能力——因为它的设计初衷就是为了简化常见的反应逻辑而牺牲了一定程度上的定制可能性。 #### 性能考量方面 从性能角度来看: - 如果只关心特定几个状态变动情况下的操作,则应该优先考虑采用针对性更强也相对轻量级一些的方法即`watch`,因为它只会针对所关注的对象建立连接,从而减少必要的计算开销. - 当涉及到复杂业务流程或者确定具体哪些部分可能会影响最终呈现结果的时候,"盲目"地利用`watchEffect`可能会带来额外负担由于每次渲染周期都会重新评估全部潜在关联项. 以下是两个方法的实际运用例子展示其各自特点: ```javascript // watch 示例 import { reactive, watch } from &#39;vue&#39;; const state = reactive({ firstName: &#39;&#39;, lastName: &#39;&#39; }); watch( () => `${state.firstName} ${state.lastName}`, (fullName) => { console.log(`Full Name Changed To:${fullName}`); } ); ``` ```javascript // watchEffect 示例 import { ref, watchEffect } from &#39;vue&#39;; const count = ref(0); watchEffect(() => { console.log(`Count is now ${count.value}.`); }); ``` ### 结论 综上所述,在实际开发过程中可以根据项目需求灵活选用合适的方案。如果希望获得更高的可控性和精确度那么推荐使用`watch`;而对于那些追求简洁快速实现简单功能模块的需求来说则可以选择更为直观易懂的方式也就是我们的老朋友--`watchEffect`. ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值