如何在React组件中获取DOM元素?

时间:2016-11-09 20:27:47

标签: javascript reactjs

我正在渲染多个相同的组件,每个组件都有自己的工具提示。我是否可以编写仅在每个组件的HTML中查找的代码,因此我不会影响具有相同类名的所有其他工具提示?我正在使用无状态组件。这是代码:

OptionsComponent.js:

import React from 'react';

const OptionsComponent = () => {
  const toggleTooltip = event => {
    document.getElementsByClassName('listings-table-options-tooltip').classList.toggle('tooltip-hide');
    event.stopPropagation();
  };
  return (
    <div className="inline-block">
        <span onClick={toggleTooltip} className="icon icon-options listings-table-options-icon"> </span>
        <div className="tooltip listings-table-options-tooltip">
            Tooltip content
        </div>
    </div>
  );
};

Backbone.js有这样的东西,允许你在view元素中开始你的文档查询范围(类似于React组件)。

4 个答案:

答案 0 :(得分:1)

使用React,您不想修改DOM。只要发生某些事情,您就可以使用新状态重新渲染组件。在您的情况下,因为您希望OptionsComponent跟踪其自己的工具提示状态,所以它实际上甚至不是无状态的。它是有状态的,所以把它作为一个组件。

它看起来像这样:

class OptionsComponent extends React.Component {
  state = {
      hide: false
  };

  toggleTooltip = (ev) => this.setState({ hide: !this.state.hide });

  render() {
      const ttShowHide = this.state.hide ? "tooltip-hide" : "";
      const ttClass = `tooltip listings-table-options-tooltip ${ttShowHide}`;
      return (
        <div className="inline-block">
            <span onClick={this.toggleTooltip} className="icon icon-options listings-table-options-icon"> </span>
            <div className={ttClass}>
                Tooltip content
            </div>
        </div>
      );

      // Alternatively, instead of toggling the tooltip show/hide, just don't render it!
      return (
        <div className="inline-block">
            <span onClick={this.toggleTooltip} className="icon icon-options listings-table-options-icon"> </span>
            {/* do not render the tooltip if hide is true */}
            {!this.state.hide && 
                <div className="tooltip listings-table-options-tooltip">
                    Tooltip content
                </div>
            }
        </div>
      );
  }
}

答案 1 :(得分:0)

您应该使用refs

从React docs稍微修改过:

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }

  focus() {
    var underlyingDOMNode = this.textInput; // This is your DOM element
    underlyingDOMNode.focus();
  }

  render() {
    // Use the `ref` callback to store a reference to the text input DOM
    // element in this.textInput.
    return (
      <div>
        <input
          type="text"
          ref={(input) => this.textInput = input} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focus}
        />
      </div>
    );
  }
}

答案 2 :(得分:0)

一种舒适的方法是以这种方式修改你的toggleTooltip方法:

...
  const toggleTooltip = event => {
      event.target.parentNode.querySelector('.tooltip').classList.toggle('tooltip-hide');
  };
...

但我会建议使用状态来表示工具提示是否显示。

答案 3 :(得分:0)

使用https://github.com/fckt/react-layer-stack你可以做同样的事情:

import React, { Component } from 'react';
import { Layer, LayerContext } from 'react-layer-stack';
import FixedLayer from './demo/components/FixedLayer';

class Demo extends Component {
  render() {
    return (
      <div>
        <Layer id="lightbox2">{ (_, content) =>
          <FixedLayer style={ { marginRight: '15px', marginBottom: '15px' } }>
            { content }
          </FixedLayer>
        }</Layer>

        <LayerContext id="lightbox2">{({ showMe, hideMe }) => (
            <button onMouseLeave={ hideMe } onMouseMove={ ({ pageX, pageY }) => {
              showMe(
                <div style={{
                      left: pageX, top: pageY + 20, position: "absolute",
                      padding: '10px',
                      background: 'rgba(0,0,0,0.7)', color: '#fff', borderRadius: '5px',
                      boxShadow: '0px 0px 50px 0px rgba(0,0,0,0.60)'}}>
                   “There has to be message triage. If you say three things, you don’t say anything.”
                </div>)
            }}>Yet another button. Move your pointer to it.</button> )}
          </LayerContext>
      </div>
    )
  }
}