React Slick与React Router Link无法区分点击和拖拽的解决方案咨询
嘿,这个问题我之前做项目时也踩过坑!React Router本身没办法帮你区分拖拽操作和点击操作——毕竟拖拽过程中也会触发点击事件,导致Link直接跳转。所以得咱们自己写点JavaScript逻辑来解决这个问题。
核心思路
咱们需要给幻灯片添加事件监听,记录用户到底是在拖拽轮播,还是真的想点击跳转。具体来说,就是判断用户的操作是否产生了足够的位移:如果鼠标/手指移动距离超过一定阈值,就判定为拖拽,不触发跳转;反之则视为点击,执行路由跳转。
针对你的类组件解决方案
我给你修改了代码,结合React Slick的事件和自定义状态来实现:
import React from "react"; import Slider from "react-slick"; import { withRouter } from "react-router-dom"; // 引入withRouter获取history对象 import "../node_modules/slick-carousel/slick/slick.css"; import "../node_modules/slick-carousel/slick/slick-theme.css"; import "./App.css"; class Movies extends React.Component { constructor() { super(); this.state = { isDragging: false }; this.handleSwipeStart = this.handleSwipeStart.bind(this); this.handleSwipeEnd = this.handleSwipeEnd.bind(this); this.handleSlideClick = this.handleSlideClick.bind(this); } // 触摸/拖拽开始时标记为拖拽状态 handleSwipeStart() { this.setState({ isDragging: true }); } // 拖拽结束后延迟重置状态,避免点击事件误触发 handleSwipeEnd() { setTimeout(() => { this.setState({ isDragging: false }); }, 250); } // 点击时判断是否为拖拽,只有非拖拽才跳转 handleSlideClick() { if (!this.state.isDragging) { this.props.history.push("/about"); } } render() { const settings = { dots: false, infinite: false, speed: 500, slidesToShow: 5, slidesToScroll: 3, arrows: false, responsive: [ { breakpoint: 1000, settings: { slidesToShow: 3, slidesToScroll: 3 } }, { breakpoint: 600, settings: { slidesToShow: 2, slidesToScroll: 2 } } ], // 绑定React Slick的拖拽事件 onSwipe: this.handleSwipeStart, onAfterChange: this.handleSwipeEnd }; return ( <div className="App"> <h2> Single Item</h2> <Slider {...settings}> <div className="slickWrapper" onClick={this.handleSlideClick}> <div className="customSlick"> <h3>1</h3> </div> </div> <div className="slickWrapper" onClick={this.handleSlideClick}> <div className="customSlick"> <h3>2</h3> </div> </div> <div className="slickWrapper" onClick={this.handleSlideClick}> <div className="customSlick"> <h3>3</h3> </div> </div> <div className="slickWrapper" onClick={this.handleSlideClick}> <div className="customSlick"> <h3>4</h3> </div> </div> <div className="slickWrapper" onClick={this.handleSlideClick}> <div className="customSlick"> <h3>5</h3> </div> </div> <div className="slickWrapper" onClick={this.handleSlideClick}> <div className="customSlick"> <h3>6</h3> </div> </div> <div className="slickWrapper" onClick={this.handleSlideClick}> <div className="customSlick"> <h3>7</h3> </div> </div> </Slider> </div> ); } } // 用withRouter包裹组件,才能获取history对象 export default withRouter(Movies);
更精准的鼠标拖拽判断(可选)
如果你的轮播需要支持鼠标拖拽,上面的onSwipe可能不够用,可以换成监听鼠标事件来判断位移:
// 在constructor里添加实例变量 constructor() { super(); this.startX = 0; this.isMouseDragging = false; this.handleMouseDown = this.handleMouseDown.bind(this); this.handleMouseMove = this.handleMouseMove.bind(this); this.handleMouseUp = this.handleMouseUp.bind(this); } handleMouseDown(e) { this.startX = e.clientX; this.isMouseDragging = false; } handleMouseMove(e) { // 移动超过10像素就判定为拖拽 if (Math.abs(e.clientX - this.startX) > 10) { this.isMouseDragging = true; } } handleMouseUp() { if (!this.isMouseDragging) { this.props.history.push("/about"); } this.isMouseDragging = false; } // 给每个slickWrapper绑定事件 <div className="slickWrapper" onMouseDown={this.handleMouseDown} onMouseMove={this.handleMouseMove} onMouseUp={this.handleMouseUp} > <div className="customSlick"> <h3>1</h3> </div> </div>
总结
React Router没有内置的拖拽/点击区分机制,必须通过自定义事件监听来实现。核心就是记录操作是否产生位移,只有在确认是纯点击的情况下,才调用路由跳转方法(history.push或者函数组件里的useNavigate)。
内容的提问来源于stack exchange,提问作者Dylan Weijgertze
相关产品推荐
相关产品推荐

