window事件监听器中调用jQuery Widget内部方法的this指向问题咨询
解决方案
核心问题是原生DOM事件回调的默认this指向绑定元素(此处为window全局作用域),与jQuery Widget的实例作用域不互通,可通过以下3种常用方案实现Widget内部属性、方法的正常访问:
方案1:缓存Widget实例的this引用(兼容性最佳,适配老项目)
在绑定事件的外层方法中提前把当前Widget实例的this存为局部变量,回调内直接调用该变量即可访问实例方法:
(function ($) { 'use strict'; $.widget("symfony.GpsPosition", { // 原有业务代码省略 listenForDeviceOrientation: function() { // 提前缓存当前Widget实例的this const self = this; window.addEventListener('deviceorientation', function (event) { console.log(event.alpha + ' : ' + event.beta + ' : ' + event.gamma); // 用缓存的self调用Widget内部方法 self.adjustHeading(event.alpha); }) }, adjustHeading: function (heading) { this.map.getModel().setViewRotation(heading, false); } }); }(jQuery));
方案2:通过bind()绑定回调的this指向
可直接把回调函数的this强制绑定为当前Widget实例,适合不需要额外声明局部变量的场景,同时方便后续解绑事件:
listenForDeviceOrientation: function() { const orientationHandler = function (event) { console.log(event.alpha + ' : ' + event.beta + ' : ' + event.gamma); // 此处this已被bind绑定为Widget实例 this.adjustHeading(event.alpha); }.bind(this); // 绑定当前Widget的this window.addEventListener('deviceorientation', orientationHandler); // 如需后续解绑事件,可将orientationHandler存为Widget实例属性,在Widget销毁逻辑中调用: // window.removeEventListener('deviceorientation', this.orientationHandler); }
方案3:ES6箭头函数写法(适配支持ES6的构建环境)
箭头函数没有独立的this作用域,会直接继承外层方法的this指向(也就是Widget实例的this),写法最简洁:
listenForDeviceOrientation: function() { window.addEventListener('deviceorientation', (event) => { console.log(event.alpha + ' : ' + event.beta + ' : ' + event.gamma); // 直接调用即可,this自动继承外层Widget实例 this.adjustHeading(event.alpha); }) }
注意:如果是单页应用或需要频繁切换页面的Symfony项目,记得在Widget内置的
_destroy生命周期钩子中手动解绑deviceorientation事件,避免调用已销毁的OpenLayers地图实例、引发内存泄漏。
内容的提问来源于stack exchange,提问作者breezy
相关产品推荐
相关产品推荐

