javascript - 为什么 forEach 可以与 e.target.children 一起使用,但不能与 getElementById 子项一起使用?

标签 javascript reactjs svg

我有一个包含多个颜色元素的 SVG/按钮。这个想法是让元素在 mouseEnter 上一个接一个地滑入,并在 mouseLeave 上从另一侧离开,然后重置,以便可以再次执行。

当使用[...e.target.children]创建数组时,后续的forEach函数可以正常工作。当使用 getElementById 并转换为数组时,我收到错误“不是函数。

前者返回实际元素的列表,而后者仅返回列表。如何正确转换数组以便 forEach 函数起作用?

<svg id="HeroButton" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 270 48">
  <title>HeroButton</title>
  <polygon className="pink" points="29 23 52 0 15 0 0 0 0 48 15 48 54 48 29 23" fill="#ed3e88"/>
  <polygon className="yellow" points="97.5 40.5 114 24 96 24 96 0 52 0 29 23 54 48 82 48 82 40.5 97.5 40.5" fill="#fded52"/>
  <polygon className="turq" points="155.5 19.5 175 0 116 0 96 0 96 24 114 24 97.5 40.5 82 40.5 82 48 116 48 156.5 48 185 19.5 155.5 19.5" fill="#17adcb"/>
  <polygon className="beige" points="224.5 33 224.5 13.5 238 0 189 0 175 0 155.5 19.5 185 19.5 156.5 48 189 48 239.5 48 224.5 33" fill="#ffffc7"/>
  <polygon className="turq2" points="243 0 238 0 224.5 13.5 224.5 33 239.5 48 243 48 270 48 270 0 243 0" fill="#17adcb"/>
</svg>
export default class HeroButton extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      translate: "translateX(100%)",
      opacity: 1
    }
  };
  componentDidMount() {
    // const polygons = [...document.getElementById('HeroButton').children;
    const polygons = Array.from(document.getElementById('HeroButton').children);
    console.log({polygons})
    this.updatePolygons(polygons);
    this.setState({
      translate: "translateX(-100%)",
      opacity: 0
    });
  };
  handleMouseEnter = (polygons) => {
    this.updatePolygons(polygons)
  };
  handleMouseLeave = (polygons) => {
    this.setState({
      translate: "translateX(100%)",
      opacity: 1
    });
  };
  updatePolygons = (polygons) => {
    // const polygons = [...e.target.children];
    polygons.forEach(child => {
      child.style.transform = this.state.translate;
      child.style.opacity = this.state.opacity;
    });
  };
  render() {
    return(
      <button>
        <HeroButtonSVG
          onMouseEnter={this.handleMouseEnter}
          onMouseLeave={this.handleMouseLeave}
        />
        <span>Check out my work<i className="fas fa-chevron-right"></i></span>
      </button>
    );
  };
};
.Hero button {
  position: relative;
  overflow: hidden;
  display: flex;
  background: transparent;
  border: none;
  transition: all .3s ease;
  text-transform: uppercase;
  outline: none;
}

.Hero button svg {
  display: flex;
  width: 275px;
  border: 1px solid white;
}

.Hero button svg polygon {
  /* transform: translateX(100%); */
  transition: all .3s ease;
}

.Hero button svg polygon.yellow {
  transition-delay: .1s;
}

.Hero button svg polygon.turq {
  transition-delay: .2s;
}

.Hero button svg polygon.beige {
  transition-delay: .3s;
}

.Hero button svg polygon.turq2 {
  transition-delay: .4s;
}

.Hero button span {
  display: inline-flex;
  position: absolute;
  top: 50%;
  left: 50%;
  white-space: nowrap;
  color: white;
  font-family: Raleway;
  font-weight: 400;
  font-size: var(--medium);
  transform: translate(-50%,-50%);
  pointer-events: none;
}

.Hero button span i {
  margin-left: var(--small);
}

最佳答案

看看这里的两段代码:

事件处理程序

  updatePolygons = (polygons) => {
    // const polygons = [...e.target.children];
    polygons.forEach(child => {
      child.style.transform = this.state.translate;
      child.style.opacity = this.state.opacity;
    });
  };

事件监听器

    <HeroButtonSVG
      onMouseEnter={this.handleMouseEnter}
      onMouseLeave={this.handleMouseLeave}
    />

传递给updatedPolygons()的值不是数组。因此它没有名为 forEach() 的方法。这就是为什么当您运行此代码时会收到错误“polygons.forEach() is not a function”。

但是,传递的实际值是事件,即一个对象{}。当您深入了解属性时,您可以访问事件数组,例如 event.target.children,这是一个可以迭代的数组。所以 .forEach() 是合法的。因此 [...event.target.children]

您似乎正在尝试使用在 componentDidMount() 中定义的 polygons 变量。但是,该多边形在 componentDidMount() 之外不可用。您可以显式创建多边形属性并从组件中的任何位置访问/改变它。

此外,我还创建了一些额外的逻辑来帮助您创建所需的动画。请参阅下面的工作代码和沙箱:

import React from "react";
import ReactDOM from "react-dom";
import HeroButtonSVG from "./HeroButtonSVG";

import "./styles.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      translate: "translateX(100%)",
      opacity: 1
    };
  }

  polygons = [];

  componentDidMount() {
    // const polygons = [...document.getElementById('HeroButton').children;
    this.polygons = Array.from(document.getElementById("HeroButton").children);
    this.setState(
      {
        translate: "translateX(100%)",
        opacity: 0
      },
      () => this.updatePolygons()
    );
  }
  handleMouseEnter = () => {
    this.setState(
      {
        translate: "translateX(0%)",
        opacity: 1
      },
      () => this.updatePolygons()
    );
  };
  handleMouseLeave = () => {
    this.setState(
      {
        translate: "translateX(100%)",
        opacity: 0
      },
      () => this.updatePolygons()
    );
  };
  updatePolygons = () => {
    // const polygons = [...e.target.children];
    this.polygons.forEach(child => {
      child.style.transform = this.state.translate;
      child.style.opacity = this.state.opacity;
    });

    console.log(this.polygons);
  };
  render() {
    return (
      <div className="Hero">
        <button>
          <HeroButtonSVG
            onMouseEnter={this.handleMouseEnter}
            onMouseLeave={this.handleMouseLeave}
          />
          <span>
            Check out my work
            <i className="fas fa-chevron-right" />
          </span>
        </button>
      </div>
    );
  }
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

因此,定义 Polygons 属性后,您可以从组件中的任何位置访问它。此外,您不需要将其显式传递给事件处理程序。只要您想使用 this.polygons 即可。

沙盒:https://codesandbox.io/s/dark-surf-v87m7

关于javascript - 为什么 forEach 可以与 e.target.children 一起使用,但不能与 getElementById 子项一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57193807/

相关文章:

javascript - 单击包含 span 的 div,不会触发 onclick 事件 - React

javascript - Canvas 最大化错误?

reactjs - 如何在react中使用redux取消之前的axios

javascript - 无法从 Redux 获取值到 props

javascript - 为什么 svg 文本标签忽略 dy 属性?

html - img 在 foreignObject 内部 在 svg 内部 在 img 内部

canvas - Fabricjs:使用导出和导入为 svg 时出现文本对齐问题

javascript - 用于压缩页内 javascript 的 Django 标记

javascript - 如何拦截或编辑柯里化(Currying)函数

javascript - 将切换按钮 onClick 绑定(bind)到 div