闭包在项目中无处不在

20 阅读2分钟

Vue 中的闭包场景

1. ‌组件私有状态管理

export default {
  data() {
    return { count: 0 };
  },
  methods: {
    createCounter() {
      let localCount = 0; // 闭包保存局部状态
      return () => {
        localCount++;
        console.log(`局部计数: ${localCount}`);
      };
    }
  },
  mounted() {
    const counter = this.createCounter();
    counter(); // 输出: 局部计数: 1
    counter(); // 输出: 局部计数: 2
  }
}

用途‌:隔离组件内部临时状态,避免污染 data‌。

2. ‌事件监听与解绑

export default {
  methods: {
    setupListener() {
      const handler = () => console.log('事件触发');
      document.addEventListener('click', handler);
      return () => document.removeEventListener('click', handler); // 返回清理闭包
    }
  },
  mounted() {
    this.cleanup = this.setupListener(); // 保存清理函数
  },
  beforeUnmount() {
    this.cleanup(); // 销毁时解绑
  }
}

用途‌:封装事件逻辑并确保销毁时释放资源‌。

3. ‌动态作用域(如 v-for 回调)

<template>
  <button v-for="(item, index) in list" 
          @click="handleClick(index)">点击{{ index }}</button>
</template>

<script>
export default {
  data() {
    return { list: ['A', 'B', 'C'] };
  },
  methods: {
    handleClick(index) {
      return () => console.log(`选中项: ${this.list[index]}`); // 闭包保留索引
    }
  }
}
</script>

用途‌:在循环中绑定事件时保留上下文‌。


React 中的闭包场景

1. ‌**useState 和 useEffect 的状态隔离**‌

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCount(c => c + 1); // 闭包获取最新 count
    }, 1000);
    return () => clearInterval(timer); // 清理闭包
  }, []);

  return <div>{count}</div>;
}

用途‌:Hooks 依赖闭包实现状态隔离和副作用管理‌。

2. ‌回调函数中的状态快照

function Form() {
  const [value, setValue] = useState('');

  const handleSubmit = useCallback(() => {
    console.log(`提交值: ${value}`); // 闭包捕获当前 value
  }, [value]); // 依赖项更新闭包

  return (
    <input value={value} onChange={(e) => setValue(e.target.value)} />
  );
}

用途‌:避免因闭包捕获旧值导致的逻辑错误‌。

3. ‌高阶组件(HOC)中的属性封装

function withLogger(WrappedComponent) {
  return function(props) {
    console.log('当前属性:', props); // 闭包访问 props
    return <WrappedComponent {...props} />;
  };
}

用途‌:增强组件功能时保留原始属性‌。


通用场景(Vue & React 均适用)

1. ‌防抖/节流函数

// Vue 示例
methods: {
  debounce(fn, delay) {
    let timer = null;
    return (...args) => { // 闭包保存 timer
      clearTimeout(timer);
      timer = setTimeout(() => fn.apply(this, args), delay);
    };
  }
}

// React 示例
const debounce = (fn, delay) => {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
};

用途‌:控制函数触发频率‌。

2. ‌工厂模式生成组件

// React 示例
const createToggle = (initialState) => {
  let isOn = initialState; // 闭包保存状态
  return function Toggle() {
    return <button onClick={() => (isOn = !isOn)}>{isOn ? 'ON' : 'OFF'}</button>;
  };
};

// Vue 示例
const createToggle = (initialState) => ({
  data: () => ({ isOn: initialState }),
  template: `<button @click="isOn = !isOn">{{ isOn ? 'ON' : 'OFF' }}</button>`
});

用途‌:动态生成可复用的组件逻辑‌。


总结

框架场景闭包作用
Vue私有状态、事件管理隔离作用域,避免污染组件实例‌
ReactHooks、HOC、回调维持状态一致性,封装逻辑‌
通用防抖节流、工厂模式控制行为,实现复用‌

通过闭包,开发者可以更灵活地管理作用域和生命周期,但需注意避免因闭包导致的内存泄漏(如未清理的定时器)或状态过期问题‌。