vue(穿透闭包/利用闭包)的几种方式

闭包

let count = 0

setInterval(() => {
  console.log(count) // ❌ 总是拿到旧值(如果 count 被闭包锁死)
}, 1000)

✅ 解决思路

核心思想就是:不要让闭包“锁死”旧的变量引用,而是通过全局/引用对象来拿“实时的”值。

方案 1:用 let 定义在外部作用域(非响应式场景:非监听值)

let count = 0

setInterval(() => {
  console.log(count) // ✅ 每次取到最新的 count
}, 1000)

setTimeout(() => {
  count = 5 // 改变外部变量
}, 3000)

⚠️ 注意:这里不能用 const,因为 const 不能重新赋值。

 

方案 2:用对象/引用来“共享”值

const state = { value: 0 }

setInterval(() => {
  console.log(state.value) // ✅ 永远是最新值
}, 1000)

setTimeout(() => {
  state.value = 10
}, 3000)

 

方案 3(在 Vue 中):用 refreactive

<script setup>
import { ref, onMounted } from 'vue'

const count = ref(0)

onMounted(() => {
  setInterval(() => {
    console.log(count.value) // ✅ 每次都是最新的值
  }, 1000)
})

// 修改值
setTimeout(() => {
  count.value = 99
}, 3000)
</script>

 

 

方案 4:用 globalThis 挂全局变量(非响应)

globalThis.count = 0

setInterval(() => {
  console.log(globalThis.count) // ✅ 始终最新
}, 1000)

setTimeout(() => {
  globalThis.count = 20
}, 3000)

总结

  • 闭包 stale value 问题 = 回调函数拿到的是“当时定义的旧变量”

  • 想要在闭包里始终取到“最新值”,必须:

    1. let/ref/reactive/对象引用

    2. 或挂到 globalThis(非响应式)

 

闭包

闭包其实就是一种“记住外部变量”的机制
如果你 想利用闭包,核心就在于:把你要“保留下来的变量”定义在 外层函数作用域,让内层函数引用它。

📌 闭包的经典定义

闭包就是 函数 + 它能访问的外部作用域

 

1. 会在闭包中读到旧值的情况

这些情况容易产生“stale value”(旧值):

ref 本身的值(解包后的 .value

const count = ref(0)

setTimeout(() => {
  console.log(count.value) 
}, 1000)

count.value = 5

如果闭包里“直接拿 count.value 的结果”,而不是引用 count,就会卡住旧值。

例子(错误写法):

const old = count.value  // ❌ 捕获的是快照
setTimeout(() => {
  console.log(old) // 永远是最初的值
}, 1000)

 

props(传入时解构过的)

<script setup>
const props = defineProps({ title: String })
const { title } = props  // ❌ 这里解构会丢响应式
setTimeout(() => {
  console.log(title)  // 永远是最初传入的 title
}, 2000)
</script>

 

响应式对象解构出来的字段

const state = reactive({ count: 0 })
const { count } = state // ❌ 这时候 count 已经是普通变量

setInterval(() => {
  console.log(count) // 永远是初始化值
}, 1000)

 

!!!!!!!!!!!不会读旧值的情况:

这些写法闭包里永远能拿到最新的值:

ref / reactive 本身(不要解构或展开)

setInterval(() => {
  console.log(count.value) // ✅ 始终是最新值
}, 1000)

toRefs 解构(保持响应式引用)

const state = reactive({ count: 0 })
const { count } = toRefs(state)  // ✅ 保持响应式

setInterval(() => {
  console.log(count.value)  // ✅ 最新值
}, 1000)

直接 watch 监听

watch(() => props.title, (val) => {
  console.log('最新 title:', val)
})

. 总结一句话

在 Vue 中:

  • 捕获“值” → 容易 stale(旧值)

  • 捕获“ref/响应式引用” → 始终最新

posted @ 2025-09-10 19:38  SimoonJia  阅读(16)  评论(0)    收藏  举报