React中如何集成现成脚本?以MousePRLX鼠标视差脚本为例
如何将原生鼠标视差脚本迁移到React项目
我有一套现成的页面布局,包含spoilers、sliders、parallax等功能脚本,现在想迁移到React项目,但之前都是从零编写代码,不清楚如何引入这些现成脚本。以下是布局阶段使用的鼠标视差脚本:
class MousePRLX { constructor(props, data = null) { let defaultConfig = { init: true, logging: true, } this.config = Object.assign(defaultConfig, props); if (this.config.init) { const paralaxMouse = document.querySelectorAll('[data-prlx-mouse]'); if (paralaxMouse.length) { this.paralaxMouseInit(paralaxMouse); } } } paralaxMouseInit(paralaxMouse) { paralaxMouse.forEach(el => { const paralaxMouseWrapper = el.closest('[data-prlx-mouse-wrapper]'); const paramСoefficientX = el.dataset.prlxCx ? +el.dataset.prlxCx : 100; const paramСoefficientY = el.dataset.prlxCy ? +el.dataset.prlxCy : 100; const directionX = el.hasAttribute('data-prlx-dxr') ? -1 : 1; const directionY = el.hasAttribute('data-prlx-dyr') ? -1 : 1; const paramAnimation = el.dataset.prlxA ? +el.dataset.prlxA : 50; let positionX = 0, positionY = 0; let coordXprocent = 0, coordYprocent = 0; // 存储动画ID,用于后续清理 el._animationId = requestAnimationFrame(setMouseParallaxStyle); if (paralaxMouseWrapper) { el._mouseMoveHandler = mouseMoveParallax.bind(null, paralaxMouseWrapper); paralaxMouseWrapper.addEventListener("mousemove", el._mouseMoveHandler); } else { el._mouseMoveHandler = mouseMoveParallax.bind(null); window.addEventListener("mousemove", el._mouseMoveHandler); } function setMouseParallaxStyle() { const distX = coordXprocent - positionX; const distY = coordYprocent - positionY; positionX = positionX + (distX * paramAnimation / 1000); positionY = positionY + (distY * paramAnimation / 1000); el.style.cssText = `transform: translate3D(${directionX * positionX / (paramСoefficientX / 10)}%,${directionY * positionY / (paramСoefficientY / 10)}%,0);`; el._animationId = requestAnimationFrame(setMouseParallaxStyle); } function mouseMoveParallax(wrapper = window) { return function(e) { const offsetTop = el.getBoundingClientRect().top + window.scrollY; if (offsetTop >= window.scrollY || (offsetTop + el.offsetHeight) >= window.scrollY) { const parallaxWidth = window.innerWidth; const parallaxHeight = window.innerHeight; const coordX = e.clientX - parallaxWidth / 2; const coordY = e.clientY - parallaxHeight / 2; coordXprocent = coordX / parallaxWidth * 100; coordYprocent = coordY / parallaxHeight * 100; } } } }); } // 添加清理方法,适配React组件卸载逻辑 stop() { const paralaxMouse = document.querySelectorAll('[data-prlx-mouse]'); paralaxMouse.forEach(el => { // 取消动画帧循环 el._animationId && cancelAnimationFrame(el._animationId); // 移除鼠标移动事件监听 const wrapper = el.closest('[data-prlx-mouse-wrapper]') || window; el._mouseMoveHandler && wrapper.removeEventListener('mousemove', el._mouseMoveHandler); // 清除元素上存储的临时属性 delete el._animationId; delete el._mouseMoveHandler; }); } }
迁移步骤
1. 封装脚本为可导出模块
在React项目的src/utils目录下新建MousePRLX.js文件,将上述修改后的脚本复制进去,最后添加导出语句:
export default MousePRLX;
2. 在React组件中引入并初始化
React组件的DOM是动态渲染的,必须在组件挂载完成后再初始化脚本,同时要在组件卸载时清理资源,避免内存泄漏。示例组件代码如下:
import { useEffect } from 'react'; import MousePRLX from '../utils/MousePRLX'; function ParallaxSection() { useEffect(() => { // 初始化视差效果 const mouseParallaxInstance = new MousePRLX({ init: true, logging: false // 生产环境建议关闭日志 }); // 组件卸载时执行资源清理 return () => { mouseParallaxInstance.stop(); }; }, []); // 空依赖数组确保只在挂载和卸载时执行一次 return ( <section> {/* 按照原布局的data属性配置视差元素 */} <div data-prlx-mouse data-prlxCx="80" data-prlxCy="80" style={{width: '300px', height: '300px', background: '#ccc', margin: '20px auto'}} > 鼠标移动查看视差效果 </div> </section> ); } export default ParallaxSection;
3. 适配动态DOM场景
如果组件存在条件渲染、列表更新等动态DOM变化,需要在DOM更新完成后重新初始化脚本。可以将相关状态变量加入useEffect的依赖数组,确保状态变化时重新执行初始化:
useEffect(() => { const mouseParallaxInstance = new MousePRLX({ init: true }); return () => mouseParallaxInstance.stop(); }, [dynamicState]); // dynamicState是触发DOM更新的状态变量
关键注意事项
- 原脚本直接操作DOM,要确保初始化时机在React完成DOM渲染之后,避免出现找不到元素的问题。
- 必须添加清理逻辑,移除事件监听并取消
requestAnimationFrame循环,防止内存泄漏。 - 如果原布局还有配套的CSS样式,需要将对应的CSS文件导入到React项目中,保证样式正常生效。
内容的提问来源于stack exchange,提问作者Default
相关产品推荐
相关产品推荐

