Skip to content

动画库直接修改 DOM 属性,跳过组件 Render 阶段 ​

本节目标:理解“动画库直接修改 DOM 属性,跳过组件 Render 阶段”的核心思路,并能把它用于实际开发或面试表达。 这个优化在业务中应该用不上,但还是非常值得学习的,将来可以应用到组件库中。

参考 [react-spring](https://github.com/pmndrs/react-spring)  的动画实现,当一个动画启动后,每次动画属性改变不会引起组件重新 Render ,而是直接修改了 dom 上相关属性值。
例子演示:[CodeSandbox](https://codesandbox.io/s/donghuakuzhijiexiugai-domtiaoguoxuanranjieduan-ij7px) 在线 Demo
import React, { useState } from "react"
import { useSpring, animated as a } from "react-spring"
import "./styles.css"
let renderCount = 0;
export function Card() {
  const [flipped, setFlipped] = useState(false)
  const { transform, opacity } = useSpring({
    opacity: flipped ? 1 : 0,
    transform: `perspective(600px) rotateX(${flipped ? 180 : 0}deg)`,
    config: { mass: 5, tension: 500, friction: 80 },
  })
  // 尽管 opacity 和 transform 的值在动画期间一直变化
  // 但是并没有组件的重新 Render
  return (
    <div onClick={() => setFlipped(state => !state)}>
      <div style={{ position: "fixed", top: 10, left: 10 }}>
        Render 次数:{++renderCount}
      </div>
      <a.div
        class="c back"
        style={{ opacity: opacity.interpolate(o => 1 - o), transform }}
      />
      <a.div
        class="c front"
        style={{
          opacity,
          transform: transform.interpolate(t => `${t} rotateX(180deg)`),
        }}
      />
    </div>
  )
}
export default Card

本站总访问 — 次