usewindowsize hook 返回响应式窗口宽高,内部用 ref 存储尺寸,onmounted 初始化并监听 resize,onunmounted 清理事件,兼容 ssr 且避免闭包重复创建。

直接封装一个 useWindowSize Hook,返回实时响应式的窗口宽高,组件内解构使用即可,无需手动管理事件监听与销毁。
核心结构:响应式变量 + 生命周期绑定
Hook 必须在内部创建 ref 存储尺寸,并利用 onMounted 和 onUnmounted 自动绑定/清理 resize 事件。关键点在于:
- 初始化时读取
window.innerWidth/window.innerHeight,但需做服务端兼容(typeof window !== 'undefined') - 监听函数必须是稳定引用(不能在每次 resize 时新建闭包),否则移除监听会失效
- 返回对象应包含
width和height两个Ref<number></number>
标准实现代码(TypeScript)
新建文件 src/composables/useWindowSize.ts:
import { ref, onMounted, onUnmounted } from 'vue'
interface WindowSize {
width: number
height: number
}
export function useWindowSize(): { width: Ref<number>; height: Ref<number> } {
const width = ref(0)
const height = ref(0)
const updateSize = () => {
width.value = window.innerWidth
height.value = window.innerHeight
}
onMounted(() => {
updateSize() // 立即获取初始值
window.addEventListener('resize', updateSize)
})
onUnmounted(() => {
window.removeEventListener('resize', updateSize)
})
return { width, height }
}
</number></number>
在组件中使用
只需导入并解构,模板中可直接绑定:
<script setup lang="ts">
import { useWindowSize } from '@/composables/useWindowSize'
const { width, height } = useWindowSize()
</script><template><div>视口:{{ width }} × {{ height }}</div>
<div v-if="width > 768">桌面布局</div>
<div v-else>移动布局</div>
</template>
进阶建议:防抖与 SSR 友好
生产环境可加简单防抖,避免频繁触发;同时确保服务端渲染不报错:
- 用
setTimeout+clearTimeout包裹updateSize,延迟 100ms 执行 - 判断
typeof window !== 'undefined'再执行所有 DOM 相关操作 - 初始值可设为
document.documentElement.clientWidth(更贴近 CSS 视口)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










