Flutter带触发操作的左右滑动容器实现需求
实现两端触发操作的滑动组件方案
核心思路
监听滑动容器的scroll事件,计算滚动位置与容器、内容的尺寸关系,判断是否到达左右两端,触发对应操作的同时加入防重复触发机制,避免多次执行。
原生JS实现示例
HTML结构
<div class="scroll-container" id="scrollContainer"> <div class="scroll-content"> <div class="item">项1</div> <div class="item">项2</div> <div class="item">项3</div> <div class="item">项4</div> <div class="item">项5</div> </div> </div>
CSS样式
.scroll-container { width: 100%; overflow-x: auto; white-space: nowrap; padding: 10px 0; -webkit-overflow-scrolling: touch; /* 优化移动端滚动流畅性 */ } .scroll-content { display: inline-block; } .item { display: inline-block; width: 200px; height: 150px; margin: 0 10px; background: #f0f0f0; line-height: 150px; text-align: center; }
JavaScript逻辑
const container = document.getElementById('scrollContainer'); let isProcessing = false; // 防重复触发锁 const tolerance = 5; // 容差,避免滚动精度问题 container.addEventListener('scroll', () => { const { scrollLeft, clientWidth, scrollWidth } = container; // 到达左端触发操作 if (scrollLeft <= tolerance && !isProcessing) { isProcessing = true; console.log('执行左端操作'); // 替换为你的业务逻辑,比如加载左侧内容 setTimeout(() => { const newItem = document.createElement('div'); newItem.className = 'item'; newItem.textContent = `新左项${Date.now()}`; container.querySelector('.scroll-content').prepend(newItem); isProcessing = false; }, 1000); } // 到达右端触发操作 if (scrollLeft + clientWidth >= scrollWidth - tolerance && !isProcessing) { isProcessing = true; console.log('执行右端操作'); // 替换为你的业务逻辑,比如加载右侧内容 setTimeout(() => { const newItem = document.createElement('div'); newItem.className = 'item'; newItem.textContent = `新右项${Date.now()}`; container.querySelector('.scroll-content').append(newItem); isProcessing = false; }, 1000); } });
Vue 3版本实现示例
<template> <div class="scroll-container" @scroll="handleScroll"> <div class="scroll-content"> <div class="item" v-for="item in items" :key="item.id"> {{ item.name }} </div> </div> </div> </template> <script setup> import { ref } from 'vue'; const items = ref(Array.from({ length: 5 }, (_, i) => ({ id: i, name: `项${i+1}` }))); const isProcessing = ref(false); const tolerance = 5; const handleScroll = (e) => { if (isProcessing.value) return; const { scrollLeft, clientWidth, scrollWidth } = e.target; // 左端触发 if (scrollLeft <= tolerance) { isProcessing.value = true; console.log('触发左端操作'); // 模拟异步加载 setTimeout(() => { const newItems = Array.from({ length: 2 }, (_, i) => ({ id: Date.now() + i, name: `新左项${i+1}` })); items.value = [...newItems, ...items.value]; isProcessing.value = false; }, 1000); } // 右端触发 if (scrollLeft + clientWidth >= scrollWidth - tolerance) { isProcessing.value = true; console.log('触发右端操作'); // 模拟异步加载 setTimeout(() => { const newItems = Array.from({ length: 2 }, (_, i) => ({ id: Date.now() + i, name: `新右项${i+1}` })); items.value = [...items.value, ...newItems]; isProcessing.value = false; }, 1000); } }; </script> <style scoped> .scroll-container { width: 100%; overflow-x: auto; white-space: nowrap; padding: 10px 0; -webkit-overflow-scrolling: touch; } .scroll-content { display: inline-block; } .item { display: inline-block; width: 200px; height: 150px; margin: 0 10px; background: #f0f0f0; line-height: 150px; text-align: center; } </style>
关键注意事项
- 防重复触发:用锁变量或节流函数控制操作执行频率,避免滚动时多次触发异步操作
- 容差设置:不要用绝对相等判断滚动位置,设置5px左右的容差适配滚动精度问题
- 异步处理:如果触发的是接口请求等异步操作,必须在操作完成后再解锁,防止并发请求
- 移动端适配:添加
-webkit-overflow-scrolling: touch;优化移动端滚动流畅度
内容的提问来源于stack exchange,提问作者Luis Jaramillo
相关产品推荐
相关产品推荐

