You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VueJS组件固定定位元素上无法触发垂直滚动问题排查

解决固定元素上滚动无法触发容器滚动的问题

问题出在固定定位的#swipe元素上:position: fixed会让元素脱离文档流,当你在这个元素上滚动时,滚动事件不会传递到父容器,且该元素本身没有可滚动内容,导致浏览器无法触发容器的滚动行为。下面是两种可行的解决方法:

方法一:CSS事件穿透(最简单)

给固定元素添加pointer-events: none,让滚动事件直接穿透到下方的可滚动容器;如果元素内有需要交互的子元素,给子元素恢复pointer-events: auto即可。

修改后的模板代码:

<template>
  <!-- 给最外层容器添加高度和滚动属性,确保它是可滚动容器 -->
  <div class="flex flex-col h-screen overflow-y-auto">
    <div id="weatherIcon" class="flex justify-end relative overflow-hidden h-1/3">
      <img class="absolute cover-enter-active max-h-full" :src="props.weather.cover" alt="Weather cover" />
    </div>
    <div id="texts" class="flex-col flex texts-enter-active pl-5">
      <div id="temperature">
        <p class="font-bold">{{ Math.round(props.temperature) }}°</p>
      </div>
      <div class="flex items-center" id="weatherDescription">
        <img :src="props.weather.icon" alt="Rain" />
        <p class="ml-1 font-light text-base">{{ props.weather.credo }}</p>
      </div>
      <div id="city">
        <p class="font-bold">{{ props.city }}</p>
      </div>
      <div id="cityDescription" class="py-5">
        <p class="font-light pr-5">{{ props.description.length > 150 ? props.description.slice(0, 150) : props.description }}... <a v-if="props.wikiLink" :href="props.wikiLink" class="font-bold" :style="{ color: weather.moreFont }">en savoir plus</a></p>
      </div>
    </div>
    <!-- 添加pointer-events: none到固定元素 -->
    <div ref="swipeElement" id="swipe" class="mt-auto mb-6 fixed bottom-0 w-full pointer-events-none">
      <!-- 子元素恢复pointer-events: auto保证交互 -->
      <div id="baseSwap" class="flex flex-col font-bold items-center swipe-enter-active w-full pointer-events-auto">
        <p>Glisser pour voyager</p>
        <img :src="swipe"  alt="Swipe icon" class="swipe opacity-80"/>
      </div>
    </div>
  </div>
</template>

方法二:JS手动转发滚动事件

如果需要保留固定元素的事件捕获能力(比如有特殊交互逻辑),可以监听固定元素的滚动相关事件,手动触发父容器的滚动:

<template>
  <div class="flex flex-col h-screen overflow-y-auto" ref="scrollContainer">
    <div id="weatherIcon" class="flex justify-end relative overflow-hidden h-1/3">
      <img class="absolute cover-enter-active max-h-full" :src="props.weather.cover" alt="Weather cover" />
    </div>
    <div id="texts" class="flex-col flex texts-enter-active pl-5">
      <div id="temperature">
        <p class="font-bold">{{ Math.round(props.temperature) }}°</p>
      </div>
      <div class="flex items-center" id="weatherDescription">
        <img :src="props.weather.icon" alt="Rain" />
        <p class="ml-1 font-light text-base">{{ props.weather.credo }}</p>
      </div>
      <div id="city">
        <p class="font-bold">{{ props.city }}</p>
      </div>
      <div id="cityDescription" class="py-5">
        <p class="font-light pr-5">{{ props.description.length > 150 ? props.description.slice(0, 150) : props.description }}... <a v-if="props.wikiLink" :href="props.wikiLink" class="font-bold" :style="{ color: weather.moreFont }">en savoir plus</a></p>
      </div>
    </div>
    <div ref="swipeElement" id="swipe" class="mt-auto mb-6 fixed bottom-0 w-full">
      <div id="baseSwap" class="flex flex-col font-bold items-center swipe-enter-active w-full">
        <p>Glisser pour voyager</p>
        <img :src="swipe"  alt="Swipe icon" class="swipe opacity-80"/>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const swipeElement = ref(null)
const scrollContainer = ref(null)
let lastTouchY = 0

onMounted(() => {
  // 处理鼠标滚轮事件
  const handleWheel = (e) => {
    e.preventDefault()
    scrollContainer.value.scrollTop += e.deltaY
  }

  // 处理触摸滑动事件
  const handleTouchMove = (e) => {
    e.preventDefault()
    const currentY = e.touches[0].clientY
    const deltaY = currentY - lastTouchY
    scrollContainer.value.scrollTop -= deltaY
    lastTouchY = currentY
  }

  swipeElement.value.addEventListener('wheel', handleWheel)
  swipeElement.value.addEventListener('touchmove', handleTouchMove, { passive: false })
})

onUnmounted(() => {
  swipeElement.value.removeEventListener('wheel', handleWheel)
  swipeElement.value.removeEventListener('touchmove', handleTouchMove)
})
</script>

关键注意点

  • 必须给最外层容器设置明确高度(比如h-screen)和overflow-y: auto/scroll,否则容器不会生成滚动条,滚动操作也不会生效。

内容的提问来源于stack exchange,提问作者dolor3sh4ze

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 08:11:02