uni-app map组件内部其他带有点击事件的标签会与map上方标签冲突,出现奇葩现象
uni-app map组件内部其他带有点击事件的标签会与map上方标签冲突,出现奇葩现象
开发环境 | 版本号 | 项目创建方式 |
---|---|---|
Windows | win11专业版21H2 | HBuilderX |
产品分类:uniapp/小程序/微信
示例代码:
<template>
<view class="my-wrap">
<view>
<view v-if="showTs" @click="onclickOne">
1
</view>
</view>
<view class="my-map-wrap">
<map id="jsmap" class="my-map" enable-3D="true" show-scale="true"
enable-building="true"
show-location="true"
:scale="19"
@markertap="onClickMarker">
<view>
<button @click="onClickMapControlGetLocal">地图定位图标</button>
</view>
</map>
</view>
<view>
<button @click="onClickTs">开始测试</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
map: {
longitude: 111.411067,
latitude: 22.189381,
scale: 19,
markers: [],
},
g_map: null,
showTs: false,
}
},
onLoad() {
},
onReady() {
this.init();
},
methods: {
init() {
this.g_map = uni.createMapContext('jsmap');
this.getLocation();
},
getLocation() {
this.g_map.moveToLocation({
longitude: this.map.longitude,
latitude: this.map.latitude,
success: (res) => {
wx.showToast({
title: '定位成功',
icon: 'success',
duration: 2000
})
},
fail: (res) => {
console.log('moveToLocation fail:' + JSON.stringify(res));
}
});
let marker = {
id: 1,
latitude: this.map.latitude,
longitude: this.map.longitude,
width: 60,
height: 60,
};
this.g_map.addMarkers([marker]);
this.g_map.addMarkers({
markers: [marker],
clear: true, // 是否先清空地图上所有 marker
success: (res) => {
// console.log('addMarkers success:' + JSON.stringify(res));
},
fail: (res) => {
console.log('addMarkers fail:' + JSON.stringify(res));
}
});
},
onClickMarker(e) {
wx.showToast({
title: '你已经点击了Marker',
icon: 'success',
duration: 2000
})
},
onclickOne() {
wx.showToast({
title: '你已经点击了1',
icon: 'success',
duration: 2000
})
},
onClickTs() {
this.showTs = true;
},
onClickMapControlGetLocal() {
wx.showToast({
title: '你已经点击了地图定位按钮',
icon: 'error',
duration: 2000
})
}
}
}
</script>
<style scoped lang="scss">
.my-wrap {
display: flex;
height: 100%;
flex-direction: column;
background: #F5F5F5;
}
.my-map-wrap {
flex: 1;
overflow: hidden;
.my-map {
width: 100%;
height: 100%;
}
}
</style>
经排查,该问题是由于微信小程序map组件markertap事件在真机上动态绑定无效导致,已向微信开发者社区反馈,可以先使用v-show绕过,后续可在帖子跟进。
大佬,我相信你的推断。只是想请教一下,为什么挪到下方,或者用v-show,就没问题?按照你的代码片段来看,是动态修改了bindmarkertap的点击事件名字。而我的这个例子,并没有改动过bindmarkertap的事件名字。这也是同一个bug导致吗?
回复 kidd: uni-app在小程序端绑定事件的元素每次切换v-if时,会动态更改后面元素所绑定的事件名,所以你挪到下方或使用v-show是不会动态更改bindmarkertap的事件名。uni-app 后续也会考虑优化这个问题。
感谢反馈,这边排查下。
在 uni-app
中使用 map
组件时,如果 map
组件内部或其他上方的标签带有点击事件,可能会出现一些意外的交互问题。这是因为 map
组件是一个原生组件,它的层级和事件处理机制与普通的 HTML
元素有所不同。以下是一些可能的原因和解决方案:
问题原因
-
层级问题:
map
组件是原生组件,其层级高于普通的HTML
元素。即使你将其他元素放置在map
组件上方,这些元素可能无法正常接收点击事件。
-
事件冒泡:
map
组件的事件可能会冒泡到父元素或上方的元素,导致这些元素的点击事件被误触发。
-
触摸事件冲突:
map
组件会捕获触摸事件(如touchstart
、touchmove
),可能会干扰上方元素的点击事件。
解决方案
1. 使用 cover-view
和 cover-image
uni-app
提供了 cover-view
和 cover-image
组件,它们可以覆盖在 map
组件上方,并且能够正常响应点击事件。将需要点击的元素替换为 cover-view
或 cover-image
。
<map>
<cover-view @click="handleClick">点击我</cover-view>
</map>
2. 调整层级关系
如果需要在上方放置普通元素,可以通过 z-index
调整层级,但要注意 map
组件的层级较高,可能仍然无法完全解决冲突。
.map-container {
position: relative;
z-index: 1;
}
.overlay {
position: absolute;
top: 0;
left: 0;
z-index: 2;
}
<view class="map-container">
<map></map>
<view class="overlay" @click="handleClick">点击我</view>
</view>
3. 阻止事件冒泡
如果 map
组件的事件冒泡到上方元素,可以在上方元素的点击事件中使用 stopPropagation
阻止事件冒泡。
<map @click="handleMapClick">
<view @click.stop="handleOverlayClick">点击我</view>
</map>
4. 使用 pointer-events
控制事件
通过 CSS 的 pointer-events
属性,可以控制元素是否接收点击事件。
.map-overlay {
pointer-events: none; /* 不接收点击事件 */
}
.clickable {
pointer-events: auto; /* 接收点击事件 */
}
<map>
<view class="map-overlay">
<view class="clickable" @click="handleClick">点击我</view>
</view>
</map>
5. 使用 position: fixed
或 position: absolute
将需要点击的元素设置为 fixed
或 absolute
定位,使其脱离 map
组件的层级影响。
.clickable {
position: fixed;
top: 20px;
left: 20px;
}
<map></map>
<view class="clickable" @click="handleClick">点击我</view>
6. 动态控制点击事件
通过动态绑定 click
事件,可以在特定条件下启用或禁用点击事件。
<map>
<view @click="isClickable ? handleClick : null">点击我</view>
</map>
export default {
data() {
return {
isClickable: true,
};
},
};