uni-app map组件内部其他带有点击事件的标签会与map上方标签冲突,出现奇葩现象

发布于 1周前 作者 gougou168 来自 Uni-App

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>

5 回复

经排查,该问题是由于微信小程序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 元素有所不同。以下是一些可能的原因和解决方案:


问题原因

  1. 层级问题

    • map 组件是原生组件,其层级高于普通的 HTML 元素。即使你将其他元素放置在 map 组件上方,这些元素可能无法正常接收点击事件。
  2. 事件冒泡

    • map 组件的事件可能会冒泡到父元素或上方的元素,导致这些元素的点击事件被误触发。
  3. 触摸事件冲突

    • map 组件会捕获触摸事件(如 touchstarttouchmove),可能会干扰上方元素的点击事件。

解决方案

1. 使用 cover-viewcover-image

uni-app 提供了 cover-viewcover-image 组件,它们可以覆盖在 map 组件上方,并且能够正常响应点击事件。将需要点击的元素替换为 cover-viewcover-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: fixedposition: absolute

将需要点击的元素设置为 fixedabsolute 定位,使其脱离 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,
    };
  },
};
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!