Получить имя тега HTML из элемента React?

#reactjs #react-jsx

#reactjs

Вопрос:

Возможно ли получить имя тега HTML из элемента React (возвращаемого из компонента)? Например:

 function Foo() {
    return <span>Hello</span>;
}
  

Имя тега HTML будет span . Я знаю, что вы можете заглянуть в type свойство элемента React, но это становится действительно сложным между SFC и обычными компонентами, и еще сложнее, когда глубина компонента довольно велика. Например:

 function Bar() {
    return <Foo />;
}
  

Все равно должно вернуться span .

Комментарии:

1. Итак, зачем вам это вообще нужно?

2. @zerkms У меня есть этот слой синтаксического анализа дерева, в котором мне нужно имя тега HTML, чтобы правильно проанализировать его в соответствии со спецификацией.

Ответ №1:

Нет.

Элементы React — это виртуальная конструкция, и они не представляют элементы DOM напрямую. Существует два типа элементов React — «обычные» элементы HTML DOM и экземпляры класса React. У первого есть «тип», потому что он чрезвычайно прост, не имеет состояния и неизменяем и создается только для отображения соответствующего элемента DOM (но не путайте его с самим элементом DOM!) Примером этого может быть <div>Foo</div> в JSX или React.createElement("div", null, "Foo") в JS.

Однако экземпляры класса React не имеют «типа», потому что они не представляют типичный элемент DOM. Когда мы создаем экземпляр класса React, мы называем его «Компонентом», чтобы идентифицировать его как отдельный экземпляр класса, имеющий render метод, инкапсулированное состояние и т.д. Невозможно получить «тип» компонента, потому что фактические элементы DOM, которые он будет отображать, полностью зависят от его внутреннего состояния и того, что render метод решает вернуть. Примером этого может быть класс React, определенный где-то, а затем созданный с помощью <Foo /> или React.createElement(Foo) .

Единственный способ узнать, какие элементы DOM на самом деле отображает компонент, — это, ну, смонтировать и отобразить его и посмотреть, что он делает. Нет «типа», присущего самому компоненту. Вы могли бы предположительно смонтировать компонент, использовать ref для захвата элемента DOM по мере его отображения, а затем использовать функцию обратного вызова для передачи этой информации обратно родительскому элементу (ам).

 var Child = React.createClass({
  render: function() {
    return <div ref={function(el){this.props.whatElementAmI(el)}.bind(this)} >Oh My!</div>
  }
});

var Parent = React.createClass({
  whatElementAmI: function(el) {
    console.log(el.nodeName); // "DIV"
  },
  render: function() {
    return <div><Child whatElementAmI={this.whatElementAmI.bind(this)} /></div>
  }
});
  

https://facebook.github.io/react/docs/glossary.html#react-elements

Комментарии:

1. Спасибо за подробный отчет. Это в значительной степени вывод, который я сделал, покопавшись, было просто любопытно, не пропустил ли я что-то. Спасибо за помощь!

Ответ №2:

ДА.

 import { renderToString } from 'react-dom/server';

const Span = () => <span>hello</span>
renderToString(<Span />)
// "<span>hello</span>"
  

затем используйте регулярное выражение для получения тега.

Ответ №3:

Вы можете использовать API верхнего уровня React для захвата узла DOM. Два предостережения: 1) это не работает с функциональными компонентами без состояния, поскольку вы не можете размещать ссылки на них, и 2) это работает только в том случае, если компонент выводит собственный элемент DOM, поэтому он не будет работать во втором случае, когда компонент выводит другой компонент React.

 import ReactDOM from 'react-dom';

class MyComponent extends React.Component {
  render() {
    return <span>Hello</span>;
  }
}

class Container extends React.Component {
  componentDidMount() {
    var domNode = ReactDOM.findDOMNode(this._component);
    console.log(domNode.tagName); // "DIV"
  }
  render() {
    return <MyComponent ref={(c) => this._component = c} />
  }
}