vue(vue3)实现监听切出当前窗口,切回当前窗口调用查询接口

文章介绍了在Vue3和Vue中处理`visibilitychange`事件的不同方法,强调了在Vue中需要正确添加和移除事件监听以避免接口被多次执行,影响性能。Vue3中使用`onMounted`,而Vue则在`created`和`destroyed`生命周期钩子中管理事件监听。

vue3中的写法

onMounted(() => {
 visibilitychange();
})
/** 浏览器窗口监听(当点击审核跳转其他系统后,数据被审批完了,再次从浏览器窗口切换,请求接口) */
const visibilitychange = () => {
  document.addEventListener('visibilitychange', function() {
    if (document.visibilityState === 'hidden') {
    } else {
      getInit() // 查询方法 - 方法中写调用接口代码
    }
  });
}

vue中的写法

created() {
    this.initList()
    document.addEventListener('visibilitychange', this.handleVisiable)
  },
  destroyed() {
    document.removeEventListener('visibilitychange', this.handleVisiable)
  },
  methods: {
    /** 切换窗口调用 */
    handleVisiable(e) {
      switch (e.target.visibilityState) {
        case 'hidden':
          console.log('离开了')
          break
        case 'visible':
          this.getInit()  // 查询方法 - 方法中写调用接口代码
          break
      }
    },
  }

注意: vue中使用,需要及时移除掉监听。比如说2个界面都写了监听方法,然后多次来回切换2个界面,多次切换不同的窗口,会导致调用的接口多次执行,影响性能

<think>我们已经在之前的答中提供了监听窗口大小变化的完整方案,包括基本实现、封装组合函数以及使用lodash防抖的优化版本。现在,根据用户当前的问题,用户明确要求使用Vue3的组合式API(Composition API)和TypeScript来实现窗口大小变化的监听。我们将结合引用内容,提供符合要求的实现。 关键点: 1. 使用组合式API(setup语法糖`<script setup>`) 2. 使用TypeScript进行类型声明 3. 实现防抖优化 4. 生命周期管理(添加和移除事件监听器) 我们将参考引用[2]中的事件监听模式(keyup事件)和生命周期钩子的使用,以及引用[3]中关于ref的说明。 方案选择: 我们将采用封装组合函数的方式,这样可以在多个组件中复用。同时,为了代码简洁,我们将使用内置的setTimeout实现防抖,但也会提供使用lodash的选项。 步骤: 1. 创建一个组合函数`useWindowResize`,它返窗口的宽度和高度(响应式引用)。 2. 在函数内部,使用ref来创建响应式变量。 3. 定义事件处理函数,并在其中更新窗口尺寸。使用防抖函数控制更新频率。 4. 在onMounted钩子中添加事件监听,在onBeforeUnmount钩子中移除事件监听。 5. 在组件中使用该组合函数。 考虑到引用[4]中使用了`toRefs`来解构响应式对象,但这里我们返的是两个ref,所以可以直接解构。 具体实现: 方案一:不使用lodash,手写防抖 ```typescript // useWindowResize.ts import { ref, onMounted, onBeforeUnmount } from &#39;vue&#39;; export default function useWindowResize(delay: number = 200) { const width = ref<number>(window.innerWidth); const height = ref<number>(window.innerHeight); let timer: ReturnType<typeof setTimeout> | null = null; const handleResize = () => { if (timer) { clearTimeout(timer); } timer = setTimeout(() => { width.value = window.innerWidth; height.value = window.innerHeight; timer = null; }, delay); }; onMounted(() => { window.addEventListener(&#39;resize&#39;, handleResize); }); onBeforeUnmount(() => { if (timer) { clearTimeout(timer); } window.removeEventListener(&#39;resize&#39;, handleResize); }); return { width, height }; } ``` 方案二:使用lodash的debounce(推荐,更简洁且功能更完善) 首先安装lodash-es(树摇优化)和类型声明文件: ```bash npm install lodash-es npm install @types/lodash-es -D ``` 然后实现: ```typescript // useWindowResize.ts import { ref, onMounted, onBeforeUnmount } from &#39;vue&#39;; import { debounce } from &#39;lodash-es&#39;; export default function useWindowResize(options?: { debounce?: number }) { const delay = options?.debounce ?? 200; const width = ref<number>(window.innerWidth); const height = ref<number>(window.innerHeight); const debouncedResize = debounce(() => { width.value = window.innerWidth; height.value = window.innerHeight; }, delay); onMounted(() => { window.addEventListener(&#39;resize&#39;, debouncedResize); }); onBeforeUnmount(() => { debouncedResize.cancel(); // 取消防抖函数的延迟调用 window.removeEventListener(&#39;resize&#39;, debouncedResize); }); return { width, height }; } ``` 在组件中使用: ```vue <template> <div> 当前窗口宽度: {{ width }}px <br> 当前窗口高度: {{ height }}px </div> </template> <script setup lang="ts"> import useWindowResize from &#39;./useWindowResize&#39;; // 使用默认防抖200ms const { width, height } = useWindowResize(); // 或者自定义防抖时间 // const { width, height } = useWindowResize({ debounce: 300 }); </script> ``` 说明: 1. 我们使用`ref`来定义宽度和高度,这是组合式API中处理基本类型响应式数据的推荐方式[^3]。 2. 在生命周期钩子中注册和移除事件监听器,避免内存泄漏[^2]。 3. 防抖处理可以避免频繁触发更新,提升性能。 注意:在TypeScript中,我们为ref指定了类型`ref<number>`,这是TypeScript的泛型语法。 如果需要在组件卸载时取消防抖函数中未执行的调用,我们使用了lodash的debounce的cancel方法(方案二)。在方案一中,我们在卸载时也清除了定时器。 这样,我们就实现了一个在Vue3组合式API中使用TypeScript监听窗口大小变化的可复用函数。 §§相关问题§§ 1. Vue3 中如何监听 DOM 元素的大小变化(使用 ResizeObserver)? 2. 如何在 Vue3 组合式函数中同时处理多个全局事件(如resize和scroll)? 3. Vue3 组合式 API 与 Vue2 选项式 API 在事件处理上有哪些主要区别? 4. 在 TypeScript 中如何为组合式函数中的事件处理器正确声明类型?</think>### Vue3 + TypeScript 组合式 API 监听窗口大小变化 在 Vue3 组合式 API 中使用 TypeScript 监听窗口大小变化,以下是完整实现方案: #### 基础实现(带防抖优化) ```vue <template> <div> 窗口宽度: {{ windowWidth }}px<br> 窗口高度: {{ windowHeight }}px </div> </template> <script setup lang="ts"> import { ref, onMounted, onBeforeUnmount } from &#39;vue&#39;; // 响应式变量 const windowWidth = ref<number>(window.innerWidth); const windowHeight = ref<number>(window.innerHeight); // 防抖处理 let debounceTimer: ReturnType<typeof setTimeout> | null = null; // 窗口大小变化处理函数 const handleResize = () => { if (debounceTimer) clearTimeout(debounceTimer); debounceTimer = setTimeout(() => { windowWidth.value = window.innerWidth; windowHeight.value = window.innerHeight; console.log(`窗口大小变化: ${windowWidth.value}x${windowHeight.value}`); }, 200); // 200ms防抖延迟 }; // 生命周期钩子 onMounted(() => { window.addEventListener(&#39;resize&#39;, handleResize); }); onBeforeUnmount(() => { window.removeEventListener(&#39;resize&#39;, handleResize); if (debounceTimer) clearTimeout(debounceTimer); }); </script> ``` #### 封装为可复用组合函数 创建 `useWindowResize.ts`: ```typescript import { ref, onMounted, onBeforeUnmount } from &#39;vue&#39;; type WindowSize = { width: number; height: number; } export default function useWindowResize( delay: number = 200 ): { width: Ref<number>; height: Ref<number> } { const size = ref<WindowSize>({ width: window.innerWidth, height: window.innerHeight }); let timer: ReturnType<typeof setTimeout> | null = null; const handler = () => { if (timer) clearTimeout(timer); timer = setTimeout(() => { size.value = { width: window.innerWidth, height: window.innerHeight }; }, delay); }; // 添加事件监听[^2] onMounted(() => window.addEventListener(&#39;resize&#39;, handler)); // 移除事件监听[^2] onBeforeUnmount(() => { window.removeEventListener(&#39;resize&#39;, handler); if (timer) clearTimeout(timer); }); return { width: ref(size.value.width), height: ref(size.value.height) }; } ``` 在组件中使用: ```vue <script setup lang="ts"> import useWindowResize from &#39;@/composables/useWindowResize&#39;; // 使用组合函数(300ms防抖) const { width, height } = useWindowResize(300); </script> <template> <div> 当前宽度: {{ width }}px <br> 当前高度: {{ height }}px </div> </template> ``` #### 使用 Lodash 优化版(推荐) ```typescript // useWindowResize.ts import { ref } from &#39;vue&#39;; import { debounce } from &#39;lodash-es&#39;; import type { DebouncedFunc } from &#39;lodash&#39;; export default function useWindowResize(delay: number = 200) { const width = ref<number>(window.innerWidth); const height = ref<number>(window.innerHeight); // 类型化防抖函数[^4] const debouncedResize: DebouncedFunc<() => void> = debounce(() => { width.value = window.innerWidth; height.value = window.innerHeight; }, delay); window.addEventListener(&#39;resize&#39;, debouncedResize); // 清理函数 const cleanup = () => { window.removeEventListener(&#39;resize&#39;, debouncedResize); debouncedResize.cancel(); }; return { width, height, cleanup }; } ``` ### 关键要点说明 1. **组合式 API 优势**: - 使用 `ref` 创建响应式数据[^3] - 逻辑封装在独立函数中,提高复用性 - 清晰的生命周期管理(`onMounted`/`onBeforeUnmount`)[^2] 2. **TypeScript 类型声明**: ```typescript // 明确变量类型 const windowWidth = ref<number>(0); // 定义尺寸类型 type WindowSize = { width: number; height: number; } // 防抖函数类型 let debounceTimer: ReturnType<typeof setTimeout>; ``` 3. **性能优化**: - 防抖处理避免频繁更新(200ms延迟) - 组件卸载时清理事件监听器和定时器[^2] - Lodash 的 `debounce` 提供更完善的防抖控制 4. **响应式处理**: - 使用 `ref` 包装基本类型值[^3] - 通过 `.value` 访问和修改响应式数据 - 自动触发组件重新渲染 ### 注意事项 1. **SSR 兼容**:在服务端渲染中需添加判断: ```typescript const width = ref(process.client ? window.innerWidth : 0); ``` 2. **移动端适配**:添加设备方向变化监听: ```typescript onMounted(() => { window.addEventListener(&#39;resize&#39;, handleResize); window.addEventListener(&#39;orientationchange&#39;, handleResize); }); ``` 3. **响应式设计**:复杂布局建议结合 CSS 媒体查询: ```css @media (max-width: 768px) { /* 移动端样式 */ } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值