Vue组件中数据无法随窗口变化实时更新的问题排查
问题原因与解决方案
问题核心是resize回调函数中的this指向错误:
你用普通function定义的onresize回调,触发时this指向的是window对象,而非Vue组件实例。所以回调里修改的this.mobile_footnote其实是给window新增了一个属性,根本没更新组件的响应式数据mobile_footnote,自然不会触发v-if的重渲染。控制台打印的也是window上的这个属性,不是组件内部的响应式变量。
修复方法(三种任选其一)
方法1:使用箭头函数
箭头函数会继承外层作用域的this(即Vue组件实例):
if (this.footnote) { // 初始化逻辑 let width = window.innerWidth; this.mobile_footnote = width < 768; // 箭头函数定义回调 const onresize = () => { width = window.innerWidth; this.mobile_footnote = width < 768; console.log(this.mobile_footnote); } window.addEventListener("resize", onresize); // 组件销毁时移除监听,避免内存泄漏 this.$once('hook:beforeUnmount', () => { window.removeEventListener("resize", onresize); }); }
方法2:提前保存Vue实例的this
把组件实例的this存入变量,回调里用该变量操作数据:
if (this.footnote) { let width = window.innerWidth; this.mobile_footnote = width < 768; const self = this; // 保存组件实例的this const onresize = function() { width = window.innerWidth; self.mobile_footnote = width < 768; console.log(self.mobile_footnote); } window.addEventListener("resize", onresize); this.$once('hook:beforeUnmount', () => { window.removeEventListener("resize", onresize); }); }
方法3:用bind绑定this
通过bind强制将回调的this绑定为Vue组件实例:
if (this.footnote) { let width = window.innerWidth; this.mobile_footnote = width < 768; function onresize() { width = window.innerWidth; this.mobile_footnote = width < 768; console.log(this.mobile_footnote); } // 绑定this后添加监听 const boundResize = onresize.bind(this); window.addEventListener("resize", boundResize); this.$once('hook:beforeUnmount', () => { window.removeEventListener("resize", boundResize); }); }
额外提示:组件销毁时必须移除resize监听,否则会造成内存泄漏,上述代码已包含移除逻辑。
内容的提问来源于stack exchange,提问作者rovac
相关产品推荐
相关产品推荐

