VueJS中实现响应window.innerWidth的计算属性
解决Vue计算属性不响应窗口resize的问题
嘿,这个问题我之前做移动端适配时也踩过坑!核心原因很简单:Vue的计算属性只会自动追踪Vue实例内的响应式依赖变化,而window.innerWidth是浏览器原生属性,不属于Vue的响应式系统,所以第一次计算后,就算窗口大小改变,计算属性也不会重新执行。
下面给你两种可行的解决方案,根据你的Vue版本选择即可:
方案一:Vue 2/3 选项式API写法
我们需要把窗口宽度转换成Vue能追踪的响应式变量,再让计算属性依赖它:
export default { data() { return { // 初始化时获取当前窗口宽度,这是响应式变量 windowWidth: window.innerWidth } }, computed: { isMobile() { // 现在依赖响应式的windowWidth,变化时会自动重新计算 return this.windowWidth <= 768 } }, mounted() { // 定义防抖函数,避免resize事件频繁触发(可选但推荐) let debounceTimer const debouncedUpdateWidth = () => { clearTimeout(debounceTimer) debounceTimer = setTimeout(() => { this.windowWidth = window.innerWidth }, 100) } // 添加窗口resize监听 window.addEventListener('resize', debouncedUpdateWidth) // 把监听函数存到实例上,方便销毁时移除 this.resizeHandler = debouncedUpdateWidth }, beforeUnmount() { // 组件销毁时移除监听,防止内存泄漏 window.removeEventListener('resize', this.resizeHandler) } }
方案二:Vue 3 组合式API写法
如果用的是Vue 3的<script setup>,写法会更简洁:
import { ref, computed, onMounted, onBeforeUnmount } from 'vue' // 响应式变量存储窗口宽度 const windowWidth = ref(window.innerWidth) // 计算属性依赖响应式变量 const isMobile = computed(() => windowWidth.value <= 768) // 防抖函数优化性能 let debounceTimer const updateWindowWidth = () => { clearTimeout(debounceTimer) debounceTimer = setTimeout(() => { windowWidth.value = window.innerWidth }, 100) } onMounted(() => { // 挂载后添加监听 window.addEventListener('resize', updateWindowWidth) }) onBeforeUnmount(() => { // 销毁前移除监听 window.removeEventListener('resize', updateWindowWidth) })
关键细节说明:
- 防抖函数:resize事件在窗口拖动时会每秒触发几十次,加防抖可以减少不必要的更新,提升页面性能,你可以根据需求调整防抖时间(比如100ms)。
- 移除监听:一定要在组件销毁时移除resize事件监听,否则组件销毁后监听还存在,会造成内存泄漏。
内容的提问来源于stack exchange,提问作者Carlos Pisarello




