微信小程序解决view点击事件穿透地图map触发markertap

微信小程序中使用map组件,ios手机中点击地图上的view,会触发底下的markertap,只要底下如果有marker点的话。

这就造成了用户体验不是很好。

然后无意间我发现点击能滑动的scroll-view反而不会触发底下的markertap,就等于是一个不穿透的容器。我就在想是不是view也可以换成scroll-view,然后防止穿透点击,答案是:可以。

但是体验还是不太好,因为scroll-view会滑动,所以按钮里面的内容也会滑动,不是最佳的解决方法。于是,我就想到可以用透明的可滑动的scroll-view放在上层作为隐形按钮,下层放普通的按钮样式,这回真正的解决了ios的bug。

一、地图上覆盖的子组件代码

wxml代码

<view class="box">
    <swiper circular>
        <swiper-item wx:for="{{switchArr}}">
            <view class="container" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">
                <view class="card">
                    <view class="content">
                        <view class="icon">
                            <image src="{{item.imageUrl}}" mode="aspectFill"></image>
                        </view>
                        <view class="bt">
                            <view class="title">{{item.name}}</view>
                        </view>
                    </view>
                </view>
            </view>
            <scroll-view class="scroll-view" scroll-y="true" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">
                <view style="height:100vh;"></view>
            </scroll-view>

        </swiper-item>
    </swiper>
    <view class="cancelSwitch" style="top:{{statusHeight+3}}px" catchtap="cancelSwitch">
        <text>退出页面</text>
    </view>

</view>

less代码

/* pages/subPack/otherAnimation/index.wxss */

page {
    box-sizing: border-box;
    font-family: sans-serif;
}

.cancelSwitch{
    position: absolute;
    left: 40rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 210rpx;
    height: 60rpx;
    line-height: 60rpx;
    border-radius: 30rpx;
    color:#fff;
    background-color: #d94251;
    image{
        width: 35rpx;
        height: 30rpx;
        margin-left: 3rpx;
    }
}
.box{
    position: fixed;
    z-index: 10000;
    min-height: 100vh;
    background-color: #1a1c22;
    width: 100%;

    swiper {
        width: 100%;
        height: 100vh;

        swiper-item {
            width: 100%;
            height: 100vh;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;

            .container {
                position: relative;
                display: flex;
                justify-content: space-around;
                align-items: center;
                width: 710rpx;

                .card {
                    width: 100%;
                    margin: 20px;
                    padding: 40px 30px;
                    border-radius: 40px;
                    background-color: #20252a;
                    border: 4rpx solid #ffefa1;
                    box-shadow: -0px -0px 10px #ffefa1;

                    .imgBx {
                        position: relative;
                        text-align: center;
                    }
                    .content {
                        text-align: center;
                        display: flex;
                        flex-wrap: wrap;
                        justify-content: center;
                        align-items: center;

                        .icon {
                            padding: 20px;
                            margin-top: 15px;
                            height: 100%;
                            width: 120%;
                            border-radius: 40px;
                            color: #32a3b1;
                            font-size: 16px;
                            overflow: hidden;
                            text-decoration: none;
                            background: #20252a;
                            box-shadow: 13px 13px 26px #181c20, -13px -13px 26px #282e35;

                            image {
                                width: 100%;
                                border-radius: 10px;
                            }
                        }

                        .bt {
                            display: inline-block;
                            padding: 10px 20px;
                            margin-top: 45px;
                            border-radius: 40px;
                            color: #ffefa1;
                            font-size: 16px;
                            text-decoration: none;
                            background: #20252a;
                            box-shadow: 20px 20px 41px #161a1d,
                                -20px -20px 41px #2a3037;

                            &:hover {
                                background: #20252a;
                                box-shadow: inset 20px 20px 41px #161a1d,
                                    inset -20px -20px 41px #2a3037;
                            }
                        }
                    }
                    &:hover {
                        background: #20252a;
                        box-shadow: inset 20px 20px 41px #161a1d,
                            inset -20px -20px 41px #2a3037;
                    }

                }
            }
            .scroll-view{
                width: 750rpx;
                background-color: #fff;
                position:absolute;
                height: 1000rpx;
                opacity: 0;
            }
        }
    }
}

js代码

const app = getApp();
Component({
  data: {
    statusHeight: app.globalData.statusHeight,
    buttonCanUse:true
  },
  properties: {
      switchArr:{
          type:Array,
          value:[]
      }
  },
  methods: {
    switchItem(e) {
        if(!this.data.buttonCanUse){
            return
        }
        this.setData({
            buttonCanUse:false
        })
        this.triggerEvent('switchItem', {
            index:e.currentTarget.dataset.index,
            name:e.currentTarget.dataset.name
        })
        this.setData({
            buttonCanUse:true
        })
    },
    cancelSwitch() {
        this.triggerEvent('cancelSwitch')
    },
  }
})

二、小程序效果

map效果:map上面有很多点位 这些点位都是可以点击进去其他页面的点

 切换旅游路线的子组件:是覆盖在map之上的一个容器 z-index:10000

点击就可以切换到路线

三、问题所在

点击这个全景路线的时候 如果点击的位置下方有一个marker点,则他触发两个点击事件,即同时切换路线 同时进入marker点链接的路径

四、解决思路

利用可滑动的scroll-view不会穿透的特性,在子组件上面插入隐形scroll-view,设置点击事件,(用户以为点击的是子组件,实际上点击的是scroll-view,这是一个通用的思路),然后将scroll-view大小覆盖子组件

五、代码分析

核心代码:

<view class="container" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">
  <view class="card">
    <view class="content">
       <view class="icon">
         <image src="{{item.imageUrl}}" mode="aspectFill"></image>
       </view>
       view class="bt">
         <view class="title">{{item.name}}</view>
       </view>
    </view>
   </view>
</view> 
<scroll-view class="scroll-view" scroll-y="true" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">
       <view style="height:100vh;"></view>
</scroll-view>
.scroll-view{
   width: 750rpx;
   background-color: #fff;
   position:absolute;
   height: 1000rpx;
   opacity: 0;
}

 <view class="container" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">是子组件里面每个路线的容器,点击可以切换路线

我在同级写了一个scroll-view 设置宽度750rpx撑满屏幕 然后高度1000rpx盖住整个路线容器 并且将透明度改为零(即opacity:0)

然后在wxml中 设置scroll-y=“true” 在scroll-view里面放一个高度100vh的盒子,让整个scroll-view可滑动,因为scroll-y,所以是上下滑动。

这里为什么不设置scroll-x=“true” 然后在横向上滑动 是因为 我本身用了swiper组件 左右滑动切换,用scroll-x的话,两个滑动事件会冲突,会影响原有的滑动感受。然后在scroll-view上

然后在scroll-view上添加原本写在container上面的点击的点击事件,让用户点的实际上是scroll-view

这样就可以保证ios系统手机点击不会穿透了。

<think>好的,我现在需要解决用户提到的UniApp开发中微信小程序点击事件失效的问题。首先,我要回忆一下UniApp和微信小程序的开发特点,以及可能引起点击事件失效的常见原因。 用户的问题是关于点击事件微信小程序中失效,可能的原因有很多。根据之前的经验,可能涉及到事件绑定方式、组件嵌套、样式影响、小程序本身的限制等。我需要逐一排查这些可能性,并结合提供的引用资料中的相关信息来寻找解决方案。 首先,检查事件绑定的语法是否正确。UniApp中使用Vue的语法,通常用@click或v-on:click来绑定事件。如果方法名拼写错误或者方法未在methods中定义,会导致事件无法触发。比如用户可能在模板中写了@click="handleClick",但methods里没有定义handleClick方法,这时候就会失效。 其次,组件嵌套问题。微信小程序中,某些组件(如scroll-view、swiper)内部的子组件可能需要特殊处理才能触发事件。比如在scroll-view里,如果子元素没有正确设置样式或事件绑定,可能导致点击无效。这时候可能需要给子元素添加CSS样式,如设置width:100%或者position: static,或者使用@tap代替@click,因为在小程序中tap事件更可靠。 第三,样式影响。如果元素的样式导致无法接收点击事件,比如元素被覆盖、透明度为0,或者使用了pointer-events: none,都会导致点击失效。需要检查CSS,确保元素可点击区域可见,并且没有其他元素遮挡。例如,引用[1]提到微信小程序的样式隔离可能导致组件样式失效,可能需要使用穿透语法,如/deep/或::v-deep,来覆盖子组件样式,但小程序默认隔离,可能需要其他方法。 另外,小程序本身的一些限制,比如按钮组件需要设置type属性,或者原生组件(如video、map)层级过高,覆盖了点击区域。比如原生组件可能无法被普通视图组件覆盖,导致事件无法触发,这时候需要调整布局或使用cover-view组件。 还有,事件冒泡的问题。如果父元素阻止了事件冒泡,或者子元素的事件没有正确传递,可能需要使用.stop修饰符来阻止冒泡,或者检查事件是否被上层元素拦截。 查看用户提供的引用资料,引用[5]中的代码示例显示使用了@click="exitMiniProgram",这可能涉及到调用微信小程序的API,如wx.exitMiniProgram,但需要确保在正确的生命周期或条件下调用,并且用户可能需要授权。此外,引用[2]提到传参的限制,虽然主要关于传参,但可能暗示某些API的调用时机限制,比如在点击事件中调用API是否受到限制。 综合以上可能性,我需要整理出常见的解决方案步骤,包括检查事件绑定、组件嵌套处理、样式调整、使用tap事件、处理原生组件层级、检查按钮属性等。同时,结合UniApp的特定情况,比如编译到小程序时的差异,可能需要使用小程序的特定事件或API。 最后,确保回答结构清晰,分点列出解决方案,并引用相关资料中的信息,如样式隔离问题,可能需要样式穿透或调整组件结构,参考引用[1]和[3]中的样式处理方式。同时,提醒用户注意小程序的原生组件限制和API调用限制,如引用[2]和[5]提到的内容。</think>在UniApp开发中,微信小程序点击事件失效可能由以下原因及解决方案导致: ### 一、事件绑定语法错误 1. **检查方法定义**:确保模板中的`@click`事件与`methods`内定义的方法名称完全一致 ```vue <button @click="handleClick">按钮</button> // methods必须包含同名函数 methods: { handleClick() { console.log("触发") } } ``` 2. **禁用语法简写**:微信小程序环境可能不识别`@click="fn(param)"`的传参形式,改用无参绑定+内部变量调用 ```vue <button @click="() => handleClick(param)">按钮</button> ``` ### 二、组件嵌套导致事件穿透 1. **层级容器限制**:在`scroll-view`/`swiper`组件内部,需为子元素添加固定宽度或`position:static` ```css .child-item { width: 100%; position: static } ``` 2. **使用`@tap`替代`@click`**:小程序的`tap`事件比`click`响应更快且穿透性更好 ```vue <view @tap="handleTap">点击区域</view> ``` ### 三、样式隔离问题 [^1] 1. **穿透组件样式**:若点击元素位于子组件内,需通过`/deep/`或`::v-deep`强制覆盖样式 ```css /deep/ .custom-btn { padding: 20rpx } ``` 2. **检查元素可见性**:通过调试工具确认元素未设置`opacity:0`或`display:none`,且未被其他元素覆盖 ### 四、原生组件层级限制 1. **规避原生组件覆盖**:`video`/`map`等原生组件默认置顶,需用`cover-view`包裹点击元素 ```vue <cover-view @click="handleNativeClick">覆盖层按钮</cover-view> ``` 2. **动态调整布局**:通过`v-if`控制原生组件显隐,或使用`position:fixed`脱离文档流 ### 五、按钮属性特殊要求 1. **设置`type`属性**:微信原生按钮需明确`type`属性值才能正常响应事件 ```vue <button type="default" @click="submit">提交</button> ``` 2. **规避表单提交冲突**:若按钮在`form`标签内,添加`form-type="button"`阻止默认提交行为 ```vue <button form-type="button" @click="customAction">独立动作</button> ``` ### 六、API调用限制 当事件中涉及微信API(如`wx.exitMiniProgram`)时,注意: 1. **用户主动触发原则**:关闭小程序等敏感操作必须由用户点击直接触发,不能通过异步回调执行 2. **授权处理**:部分API需在`<button open-type="...">`中配置开放能力[^5]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值