试试试试
试试试试
  • 发布:2026-06-14 17:10
  • 更新:2026-06-14 17:10
  • 阅读:95

页面如果渲染了input组件,监听触摸的事件处理,就会变得非常卡,是什么问题

分类:uni-app

比如页面中有个拖动跟随的功能,监听touch相关事件处理,正常使用是非常流畅的。
一旦页面中使用了 input 组件(其他因素全部相同),拖动时就会变得非常卡,一顿一顿的。
必须要用v-if注销掉input组件才行,v-show隐藏都没用。

这是什么问题呢

2026-06-14 17:10 负责人:无 分享
已邀请:
Ask小助手

Ask小助手 - Ask社区AI助手

欢迎到专业群( uni-app 官方技术交流群 1 ) 咨询,群中有相关专业的管理员和群友。

这个问题是典型的 WebView 内核 Bug 导致的触摸事件冲突,在 uni-app 的 App 端(特别是 Android)中比较常见。


问题根源

根据 DCloud 官方的说明,这是 Android System WebView 的已知 Bug(从 66.0.3359.126 版本到最新都存在):

当 WebView 页面中存在持续渲染的元素时(如 input 组件获得焦点后的光标闪烁、键盘弹起等),页面隐藏后会导致 JS 阻塞,进而影响触摸事件的处理效率,造成拖动卡顿。

具体到你的场景:

  1. input 组件在页面中渲染时,即使没有获得焦点,它也会作为原生组件存在于渲染树中
  2. input 组件在某些情况下会触发持续的布局计算或事件监听(如键盘高度变化监听、光标闪烁等)
  3. 这些持续的计算会与你的 touch 事件处理产生竞争,导致触摸回调的执行频率下降
  4. 因为 v-show 只是 CSS 隐藏,组件仍然存在于 DOM 树中,所以卡顿依然存在
  5. 只有 v-if 彻底销毁组件,才能消除这种竞争

这也解释了为什么:

  • 没有 input 组件时,拖动非常流畅
  • v-show 隐藏无效(因为组件还在 DOM 中)
  • v-if 注销后才恢复正常(组件被完全移除)

解决方案

方案一:页面隐藏时暂停持续渲染(推荐)

在你的页面中监听 onHideonShow 生命周期,暂停/恢复可能造成持续渲染的逻辑:

export default {  
  data() {  
    return {  
      isPageVisible: true  
    }  
  },  
  onShow() {  
    this.isPageVisible = true;  
    // 恢复你的拖动相关逻辑  
  },  
  onHide() {  
    this.isPageVisible = false;  
    // 暂停持续渲染的逻辑,比如停止动画、定时器等  
  },  
  methods: {  
    handleTouchMove(e) {  
      if (!this.isPageVisible) return; // 页面隐藏时不处理  
      // 你的拖动跟随逻辑  
    }  
  }  
}

本助手使用国产模型,生成代码可能不准确。专业的代码生成需要全球顶尖的AI Coding模型。推荐使用uni-agent

方案二:使用 WebView 的 pause/resume 方法(App 端)

在页面隐藏时主动暂停 WebView 的 JS 和渲染,显示时恢复:

export default {  
  onShow() {  
    // #ifdef APP-PLUS  
    const currentWebview = this.$mp.page.$getAppWebview();  
    if (currentWebview.isPause && currentWebview.isPause()) {  
      currentWebview.resume();  
    }  
    // #endif  
  },  
  onHide() {  
    // #ifdef APP-PLUS  
    const currentWebview = this.$mp.page.$getAppWebview();  
    if (currentWebview.pause) {  
      currentWebview.pause();  
    }  
    // #endif  
  }  
}

本助手使用国产模型,生成代码可能不准确。专业的代码生成需要全球顶尖的AI Coding模型。推荐使用uni-agent

注意:这个方法需要 HBuilderX 2.3.8 及以上版本支持。

方案三:优化 input 组件的使用

  1. 延迟渲染 input:在页面加载完成后延迟 100-300ms 再渲染 input 组件,避免与页面初始化动画抢资源
  2. 使用 nvue 页面:nvue 使用原生渲染引擎,不存在 WebView 的这个问题,input 和触摸事件的冲突可以避免
  3. 减少持续渲染:如果 input 不需要自动聚焦,设置 :focus="false";避免在 input 上使用实时计算的样式
export default {  
  data() {  
    return {  
      showInput: false  
    }  
  },  
  onReady() {  
    // 延迟渲染 input,避免与页面初始化抢资源  
    setTimeout(() => {  
      this.showInput = true;  
    }, 300);  
  }  
}

本助手使用国产模型,生成代码可能不准确。专业的代码生成需要全球顶尖的AI Coding模型。推荐使用uni-agent

方案四:条件编译处理(临时方案)

如果上述方案都不理想,可以在拖动交互时临时隐藏 input:

data() {  
  return {  
    isDragging: false  
  }  
},  
methods: {  
  handleTouchStart() {  
    this.isDragging = true;  
  },  
  handleTouchEnd() {  
    this.isDragging = false;  
  }  
}

本助手使用国产模型,生成代码可能不准确。专业的代码生成需要全球顶尖的AI Coding模型。推荐使用uni-agent

模板中:

<input v-if="!isDragging" />

本助手使用国产模型,生成代码可能不准确。专业的代码生成需要全球顶尖的AI Coding模型。推荐使用uni-agent


总结

这个问题的本质是 Android WebView 内核缺陷导致的触摸事件和 input 组件渲染竞争。最根本的解决方案是:

  • 切换到 nvue 页面(原生渲染,无此问题)
  • 或者在使用 vue 页面时,通过 onHide/onShow 生命周期管理来避免不必要的持续渲染

参考 DCloud 官方文章:Android webview隐藏后跳转新页面input输入卡顿与白屏渲染慢的问题说明及修复方案

内容为 AI 生成,仅供参考

要回复问题请先登录注册