uni-app nvue 界面元素绑定的事件点击无效 发生v-if或是其他交互后事件全部失效点击没有反应

uni-app nvue 界面元素绑定的事件点击无效 发生v-if或是其他交互后事件全部失效点击没有反应

开发环境 版本号 项目创建方式
Mac 15.3 HBuilderX

产品分类:uniapp/App

PC开发环境操作系统:Mac

HBuilderX类型:正式

HBuilderX版本号:4.66

手机系统:Android

手机系统版本号:Android 11

手机厂商:华为

手机机型:荣耀play

页面类型:nvue

vue版本:vue2

打包方式:云端

示例代码:

总共三个nvue文件:
c-list.nvue
c-modal.nvue
map.nvue
<template>  
    <view class="map-container">  
        <view style="flex:1;background:blue;"></view>  
        <!-- 真机再用map替换显示 不然模拟器很卡容易异常死机-->  
        <!-- <map style="flex:1"></map> -->  
    </view>  

    <!-- 全屏覆盖层 -->  
    <cover-view class="cover-view1">  
        <view class="view1">  
            <view class="btns" v-if="isShowBtns">  
                <view class="btn" >  
                    <text class="btn" @click="tab(1)" :class="{'active1': activeIndex === 1}">普通</text>  
                </view>  
                <view class="btn" @click="tab(2)">  
                    <text class="btn" :class="{'active2': activeIndex === 2}">卫星</text>  
                </view>  
            </view>  

            <view class="add-marker" v-else>  
                <text class="save-btn" @click="save()">保存</text>  
                <image class="marker" src="../../static/images/location.png"></image>  
            </view>  
        </view>  

        <view class="view2">  
            <image class="image" src="../../static/images/location.png" @click="getLocation()"></image>  
            <view class="camera-list" @click="openList1()">  
                <text class="camera-text">相机列表</text>  
            </view>  
        </view>  

        <view>  
            <c-model ref="model1" :dataList="dataList1" @clickItem="openList2"></c-model>  
            <c-model ref="model2" :dataList="dataList2" :isItemCloseModal="false"></c-model>  
        </view>  
    </cover-view>  
</template>  
<style lang="scss">  
$border: 1px solid transparent;  
$btnRedius: 40rpx;  

.map-container{  
    flex: 1;  
    border: $border;  
}  

.cover-view1{  
    position: absolute;  
    top: 50px;  
    left: 0;  
    right: 0;  
    bottom: 100rpx;  
    border: $border;  
    display: flex;  
    flex-direction: column;  
    justify-content: space-between;  
}  

.view1{  
    border: $border;  
    height: 200px;  
    pointer-events: none; /* 允许点击穿透到下层 */  
}  
.btns {  
    display: flex;  
    flex-direction: row;  
    margin: 10px;  
    border-radius: $btnRedius;  
    background: #ccc;  
}  
.btn{  
    flex: 1;  
    height: 40px;  
    line-height: 40px;  
    text-align: center;  
    color: #fff;  
    font-size: 15px;  
    font-weight: bold;  
    border: $border;  
}  
.active1{  
    background: green;  
    border-top-left-radius: $btnRedius;  
    border-bottom-left-radius: $btnRedius;  
}  
.active2{  
    background: green;  
    border-top-right-radius: $btnRedius;  
    border-bottom-right-radius: $btnRedius;  
}  

.view2{  
    // flex: 1 等价于 100%,默认是column方向的100%;   
    // 可以通过改变方向row; 还有width:750rpx也是100%意思  
    height: 350rpx;  
    width: 750rpx;  
    border: $border;  
    pointer-events: auto; /* 子元素恢复点击 */  
}  
.image{  
    position: absolute;  
    width: 40px;  
    height: 40px;  
    bottom: 250rpx;  
    left: 20rpx;  
}  
.camera-list{  
    position: absolute;  
    left: 0;  
    right: 0;  
    bottom: 0;  
    padding: 10px;  
    background: rgba(0,0,0,0.3);  
}  
.camera-text{  
    color: #fff;  
}  

.add-marker{  
    flex: 1;  
    display: flex;   
    align-items: center;   
    height: 200rpx;  
}  
.save-btn{  
    position: absolute;  
    top: 10px;  
    right: 10px;  
    width: 100px;  
    height: 40px;  
    line-height: 40px;  
    text-align: center;  
    background: green;  
    color: #fff;  
}  
.marker{  
    width: 40px;  
    height: 40px;  
    top: 100px;  
}  
</style>
<template>  
  <view class="container">  
    <!-- 遮罩层(重新启用并优化) -->  
    <!-- <view   
      v-if="isShowModal && showModal"   
      class="mask"   
      @click="closeModal"  
      :style="{opacity: maskOpacity}"  
    ></view> -->  

    <!-- 弹窗内容 -->  
    <view v-if="showModal">  
      <view   
        class="modal"   
        ref="animElement"   
        :style="{height: actualMaxHeight}"  
      >  
        <view class="modal-content">  
          <!-- 弹窗头部 -->  
          <view class="modal-header">  
            <view class="modal-title">  
              <text class="title" v-if="title">{{title}}</text>  
            </view>  
            <view class="close-wrapper" @click="closeModal">  
              <image  
                class="close"   
                src="../../static/images/close.png"   
              ></image>  
            </view>  
          </view>  

          <!-- 可滚动内容区域 -->  
          <scroll-view class="scroll-list" scroll-y>  
            <c-list :dataList="dataList" @clickItem="clickItem"></c-list>  
          </scroll-view>  
        </view>  
      </view>  
    </view>  
  </view>  
</template>
<template>  
  <scroll-view class="scroll-view" scroll-y="true">  
    <recycle-list   
      for="(item, i) in longList"  
      key-field="id"  
      style="width: 750rpx;"  
    >  
      <cell-slot scope="item">  
        <view class="item" @click="handleItemClick(item)">  
          <text class="item-text">{{item.name}}</text>  
          <text class="item-image">{{item.isChecked ? '✅' : '未选中'}}</text>  
        </view>  
      </cell-slot>  
    </recycle-list>  
  </scroll-view>  
</template>

更多关于uni-app nvue 界面元素绑定的事件点击无效 发生v-if或是其他交互后事件全部失效点击没有反应的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

试一下别v-if隐藏view,通过透明度opacity来隐藏需要隐藏的view;

更多关于uni-app nvue 界面元素绑定的事件点击无效 发生v-if或是其他交互后事件全部失效点击没有反应的实战教程也可以访问 https://www.itying.com/category-93-b0.html


我尝试一下, 如果不行,我再用subNVue这种方式看看

opactiy 这种方式可以,但是毕竟占位置; 我把弹窗内容单独用subNVue这种方式实现了,然后原来的界面上元素v-if 交互的内容发现又可以点击了,事件又没有问题了;

自己摸索出来的方式
解决方式:

对于弹窗类的内容,用subNVue实现 这样理论上事件是完全隔离的
对于界面上元素v-if控制,界面简单的话,没啥问题,复杂的话我估计还是有这种问题的 (deepseek回答的是布局层级不能保证,导致事件触发错误或是不生效) 如果发现事件失效,尝试用opacity去控制交互,保证界面元素不丢失(这种的话理论上事件不会丢失绑定对象)

在nvue最好别使用v-if控制view的隐显,你可以简单测试一下,不断的显隐view控件,app的内存占用是不断叠加上升的;

这是一个典型的nvue页面事件绑定失效问题,主要原因是pointer-events属性的不当使用和cover-view在nvue中的特殊表现。

问题分析:

  1. pointer-events冲突:在.view1中设置了pointer-events: none,这会使其所有子元素(包括按钮)都无法响应点击事件。虽然.view2设置了pointer-events: auto,但.view1中的按钮点击仍然失效。

  2. cover-view在nvue中的限制:nvue页面的cover-view与vue页面表现不同,事件绑定可能受到渲染层级影响。

  3. v-if切换导致的事件丢失:当isShowBtns状态变化时,DOM重新渲染可能造成事件绑定失效。

解决方案:

  1. 移除pointer-events限制
.view1{
    border: $border;
    height: 200px;
    /* 移除 pointer-events: none */
}
  1. 检查cover-view使用:确保所有需要交互的元素都在cover-view内,且没有层级遮挡。

  2. 优化v-if使用:考虑使用v-show替代v-if,避免DOM频繁销毁重建:

<view class="btns" v-show="isShowBtns">
<view class="add-marker" v-show="!isShowBtns">
回到顶部