React JS移动端OnClick事件失效问题求助
移动端点击签名组件按钮无响应,仅点击外部区域生效
问题描述
验证签名时,电脑端点击组件的确认/取消按钮能正常触发onSet()/onCancel()函数,但平板/移动端点击按钮时函数无响应,只有点击按钮以外的签名区域时,相关点击逻辑才生效。需要实现移动端点击按钮也能触发对应函数。
相关代码
DraggableSignature组件
//DraggableSignature.js import Draggable from "react-draggable"; import { FaCheck, FaTimes } from "react-icons/fa"; import { errorColor, goodColor, primary45 } from "../utils/colors"; export default function DraggableSignature({ url, onEnd, onSet, onCancel }) { const styles = { container: { position: "absolute", zIndex: 100000, border: `2px solid ${primary45}`, }, controls: { position: "absolute", right: 0, display: "inline-block", backgroundColor: primary45, // borderRadius: 4, }, smallButton: { display: "inline-block", cursor: "pointer", padding: 4, }, }; return ( <Draggable onStop={onEnd}> <div style={styles.container}> <div style={styles.controls}> <button style={styles.smallbutton} onClick={onSet}> <FaCheck color={goodColor} /> </button> <button style={styles.smallbutton} onClick={onCancel}> <FaTimes color={errorColor} /> </button> </div> <img alt="signature" src={url} width={200} style={styles.img} draggable={false} /> </div> </Draggable> ); }
App.js中组件调用代码
{signatureURL ? ( <DraggableSignature url={signatureURL} onCancel={() => { setSignatureURL(null); }} onSet={async () => { const { originalHeight, originalWidth } = pageDetails; const scale = originalWidth / documentRef.current.clientWidth; const y = documentRef.current.clientHeight - (position.y - position.offsetY + 64 - documentRef.current.offsetTop); const x = position.x - 160 - position.offsetX - documentRef.current.offsetLeft; // new XY in relation to actual document size const newY = (y * originalHeight) / documentRef.current.clientHeight; const newX = (x * originalWidth) / documentRef.current.clientWidth; const pdfDoc = await PDFDocument.load(pdf); const pages = pdfDoc.getPages(); const firstPage = pages[pageNum]; const pngImage = await pdfDoc.embedPng(signatureURL); const pngDims = pngImage.scale(scale * 0.3); firstPage.drawImage(pngImage, { x: newX, y: newY, width: pngDims.width, height: pngDims.height, }); if (autoDate) { firstPage.drawText( `Signé électroniquement le :${dayjs().format( "DD/MM/YYYY à HH:mm:ss" )}`, { x: newX, y: newY - 10, size: 14 * scale, color: rgb(0.074, 0.545, 0.262), } ); } const pdfBytes = await pdfDoc.save(); const blob = new Blob([newUint8Array(pdfBytes)]); const URL = await blobToURL(blob); setPdf(URL); setPosition(null); setSignatureURL(null); }} onEnd={setPosition} /> ) : null}
已尝试的无效方案
- 将按钮
onClick事件替换为onTouchStart - 调整按钮位置样式
- 更换CSS库
解决方案
问题根源是react-draggable会优先捕获移动端的触摸事件,导致按钮的点击事件被拦截。结合代码中的拼写错误,可通过以下方式修复:
1. 修正样式拼写错误 + 利用react-draggable内置忽略规则
代码中样式属性styles.smallbutton拼写错误(定义时为smallButton),会导致按钮样式失效,影响可点击区域。同时给按钮添加data-no-drag属性,让react-draggable忽略该元素的拖拽事件:
<button style={styles.smallButton} onClick={onSet} data-no-drag> <FaCheck color={goodColor} /> </button> <button style={styles.smallButton} onClick={onCancel} data-no-drag> <FaTimes color={errorColor} /> </button>
2. 手动阻止事件冒泡
通过在按钮点击事件中阻止事件冒泡,避免react-draggable捕获事件:
<button style={styles.smallButton} onClick={(e) => { e.stopPropagation(); onSet(); }} > <FaCheck color={goodColor} /> </button> <button style={styles.smallButton} onClick={(e) => { e.stopPropagation(); onCancel(); }} > <FaTimes color={errorColor} /> </button>
内容的提问来源于stack exchange,提问作者Pierre Dumay
相关产品推荐
相关产品推荐

