React组件调用外部anime.js动画函数出现不可达代码及DOM为空问题
问题原因
render方法中return语句后的代码永远不会被执行,JavaScript执行到return就会跳出当前函数,因此写在return后的letterStagger()属于不可达代码,触发对应警告。- 若在DOM未完成挂载时调用动画函数,
document.querySelector无法匹配到还未渲染到页面的元素,会返回null,操作null的textContent属性自然会触发报错。
解决方法
类组件的componentDidMount生命周期钩子会在组件首次挂载到真实DOM之后触发,此时对应元素已经完成渲染,直接在这个钩子中调用动画函数即可。
基础修复代码
import React from 'react'; import { letterStagger } from "../../utils/animations"; class Hero extends React.Component{ // 组件挂载完成后执行动画 componentDidMount() { letterStagger(); } render(){ return ( <section className="hero"> <h1 className="hero__title"> <span className="hero__title-inner"> <span className="hero__title-letters">This is the title</span> </span> </h1> </section> ) } } export default Hero;
优化方案(推荐)
为了避免全局document.querySelector在页面存在多个Hero组件时出现匹配冲突,可以使用React的ref直接传递目标DOM元素给动画函数:
- 修改
animations.js,改为接收目标元素作为参数:
import anime from 'animejs/lib/anime.es.js'; export function letterStagger(textWrapper){ textWrapper.innerHTML = textWrapper.textContent.replace(/\S/g, "<span class='hero__title-letter'>$&</span>"); anime.timeline({loop: true}) .add({ targets: textWrapper.querySelectorAll('.hero__title-letter'), translateY: ["1.1em", 0], translateZ: 0, duration: 750, delay: (el, i) => 50 * i }).add({ targets: textWrapper.closest('.hero__title'), opacity: 0, duration: 1000, easing: "easeOutExpo", delay: 1000 }); }
- 修改
Hero组件,通过ref传递元素:
import React from 'react'; import { letterStagger } from "../../utils/animations"; class Hero extends React.Component{ constructor(props) { super(props); // 创建ref引用 this.titleLetterRef = React.createRef(); } componentDidMount() { // 把获取到的DOM元素传给动画函数 letterStagger(this.titleLetterRef.current); } render(){ return ( <section className="hero"> <h1 className="hero__title"> <span className="hero__title-inner"> {/* 绑定ref到目标元素 */} <span ref={this.titleLetterRef} className="hero__title-letters">This is the title</span> </span> </h1> </section> ) } } export default Hero;
内容的提问来源于stack exchange,提问作者Freddy
相关产品推荐
相关产品推荐

