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
相关产品推荐
相关产品推荐

