Angular TypeScript中OpenLayers 7的map.forEachFeatureAtPixel()报错问题
问题
代码在普通JavaScript中可正常运行,但在Angular的TypeScript环境中报错,提示this.map.forEachFeatureAtPixel()中的this.map未定义,无法读取其属性。需求是实现地图点击多选要素功能,将singleclick事件绑定到getmultiplefeaturesatpixel函数后,该函数内的this.map为undefined。代码如下:
public selected: Collection<Feature<any>> = new Collection(); multiSelectFeatures(): void { this.clearInteractions(); this.ClearSelection(); if (this.selected instanceof Collection) { this.selected.forEach(function (feature) { feature.setStyle(undefined); }); this.selected.clear(); } this.map.on("singleclick", this.getmultiplefeaturesatpixel); } getmultiplefeaturesatpixel(evt: { pixel: Pixel }): void { this.map.forEachFeatureAtPixel(evt.pixel, (feature): void => { if (feature instanceof Feature) { const featureArray = this.selected.getArray(); const selIndex = featureArray.indexOf(feature); if (selIndex === -1) { this.selected.push(feature); console.log(feature); // this.selected.getArray().forEach((feat) => feat.setStyle(editOperations.highlightStyle)); } else { this.selected.remove(feature); feature.setStyle(undefined); } } }); }
解决方法
这个问题的核心是函数作为事件回调时this指向丢失:直接将this.getmultiplefeaturesatpixel传给map.on时,回调执行的this会指向触发事件的地图实例,而非当前组件实例,导致this.map变为undefined。
有三种可行的修复方式:
方式1:用箭头函数包裹回调
箭头函数会继承外层作用域的this,确保回调内的this指向组件实例:
multiSelectFeatures(): void { this.clearInteractions(); this.ClearSelection(); if (this.selected instanceof Collection) { this.selected.forEach(function (feature) { feature.setStyle(undefined); }); this.selected.clear(); } // 用箭头函数包裹回调,保留组件this指向 this.map.on("singleclick", (evt) => this.getmultiplefeaturesatpixel(evt)); }
方式2:用bind(this)强制绑定指向
在绑定事件时,通过bind将回调函数的this强制绑定到当前组件实例:
multiSelectFeatures(): void { this.clearInteractions(); this.ClearSelection(); if (this.selected instanceof Collection) { this.selected.forEach(function (feature) { feature.setStyle(undefined); }); this.selected.clear(); } // 绑定this到组件实例 this.map.on("singleclick", this.getmultiplefeaturesatpixel.bind(this)); }
方式3:将回调定义为箭头函数
直接把getmultiplefeaturesatpixel定义成箭头函数,它的this会始终指向组件实例,无需额外绑定:
public selected: Collection<Feature<any>> = new Collection(); multiSelectFeatures(): void { this.clearInteractions(); this.ClearSelection(); if (this.selected instanceof Collection) { this.selected.forEach(function (feature) { feature.setStyle(undefined); }); this.selected.clear(); } this.map.on("singleclick", this.getmultiplefeaturesatpixel); } // 改为箭头函数,this始终指向组件实例 getmultiplefeaturesatpixel = (evt: { pixel: Pixel }): void => { this.map.forEachFeatureAtPixel(evt.pixel, (feature): void => { if (feature instanceof Feature) { const featureArray = this.selected.getArray(); const selIndex = featureArray.indexOf(feature); if (selIndex === -1) { this.selected.push(feature); console.log(feature); // this.selected.getArray().forEach((feat) => feat.setStyle(editOperations.highlightStyle)); } else { this.selected.remove(feature); feature.setStyle(undefined); } } }); }
内容的提问来源于stack exchange,提问作者Marudi Abhinaya
相关产品推荐
相关产品推荐

