Содержание

Рефы и DOM – React

Рефы дают возможность получить доступ к DOM-узлам или React-элементам, созданным в рендер-методе.

В обычном потоке данных React родительские компоненты могут взаимодействовать с дочерними только через пропсы. Чтобы модифицировать потомка, вы должны заново отрендерить его с новыми пропсами. Тем не менее, могут возникать ситуации, когда вам требуется императивно изменить дочерний элемент, обойдя обычный поток данных. Подлежащий изменениям дочерний элемент может быть как React-компонентом, так и DOM-элементом. React предоставляет лазейку для обоих случаев.

Когда использовать рефы

Ситуации, в которых использование рефов является оправданным:

  • Управление фокусом, выделение текста или воспроизведение медиа.
  • Императивный вызов анимаций.
  • Интеграция со сторонними DOM-библиотеками.

Избегайте использования рефов в ситуациях, когда задачу можно решить декларативным способом.

Например, вместо того чтобы определять методы open() и close() в компоненте Dialog, лучше передавать ему проп isOpen.

Не злоупотребляйте рефами

Возможно, с первого взгляда вам показалось, что рефы применяются, когда нужно решить какую-то задачу в вашем приложении «во что бы то ни стало». Если у вас сложилось такое впечатление, сделайте паузу и обдумайте, где должно храниться конкретное состояние в иерархии компонентов. Часто становится очевидно, что правильным местом для хранения состояния является верхний уровень в иерархии. Подробнее об этом — в главе Подъём состояния.

Примечание

Приведённые ниже примеры были обновлены с использованием API-метода React.createRef() добавленного в React 16.3. Если вы используете более старую версию React, мы рекомендуем использовать колбэк-рефы.

Создание рефов

Рефы создаются с помощью React.createRef() и прикрепляются к React-элементам через ref атрибут. Обычно рефы присваиваются свойству экземпляра класса в конструкторе, чтобы на них можно было ссылаться из любой части компонента.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();  }
  render() {
    return <div ref={this.myRef} />;  }
}

Доступ к рефам

Когда реф передаётся элементу в методе render, ссылка на данный узел доступна через свойство рефа current.

const node = this.myRef.current;

Значение рефа отличается в зависимости от типа узла:

  • Когда атрибут ref используется с HTML-элементом, свойство current созданного рефа в конструкторе с помощью React.createRef() получает соответствующий DOM-элемент.
  • Когда атрибут
    ref
    используется с классовым компонентом, свойство current объекта-рефа получает экземпляр смонтированного компонента.
  • Нельзя использовать ref атрибут с функциональными компонентами, потому что для них не создаётся экземпляров.

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

Добавление рефа к DOM-элементу

В представленном ниже примере ref используется для хранения ссылки на DOM-элемент.

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

  focusTextInput() {
    
    
    this.textInput.current.focus();  }

  render() {
    
    
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />        <input
          type="button"
          value="Фокус на текстовом поле"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

React присвоит DOM-элемент свойству current при монтировании компонента и присвоит обратно значение null при размонтировании. Обновление свойства ref происходит перед вызовом методов componentDidMount и componentDidUpdate.

Добавление рефа к классовому компоненту

Для того чтобы произвести имитацию клика по CustomTextInput из прошлого примера сразу же после монтирования, можно использовать реф, чтобы получить доступ к пользовательскому

<input> и явно вызвать его метод focusTextInput:

class AutoFocusTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();  }

  componentDidMount() {
    this.textInput.current.focusTextInput();  }

  render() {
    return (
      <CustomTextInput ref={this.textInput} />    );
  }
}

Обратите внимание, что это сработает только в том случае, если CustomTextInput объявлен как классовый компонент:

class CustomTextInput extends React.Component {  
}
Рефы и функциональные компоненты

По умолчанию нельзя использовать атрибут ref с функциональными компонентами, потому что для них не создаётся экземпляров:

function MyFunctionComponent() {  return <input />;
}

class Parent extends React.
Component { constructor(props) { super(props); this.textInput = React.createRef(); } render() { return ( <MyFunctionComponent ref={this.textInput} /> ); } }

Если вам нужен реф на функциональный компонент, можете воспользоваться forwardRef (возможно вместе с useImperativeHandle), либо превратить его в классовый компонент.

Тем не менее, можно использовать атрибут ref внутри функционального компонента при условии, что он ссылается на DOM-элемент или классовый компонент:

function CustomTextInput(props) {
    const textInput = useRef(null);
  function handleClick() {
    textInput.current.focus();  }

  return (
    <div>
      <input
        type="text"
        ref={textInput} />      <input
        type="button"
        value="Фокус на поле для ввода текста"
        onClick={handleClick}
      />
    </div>
  );
}

Передача DOM-рефов родительским компонентам

В редких случаях вам может понадобиться доступ к дочернему DOM-узлу из родительского компонента. В общем случае, такой подход не рекомендуется, т. к. ведёт к нарушению инкапсуляции компонента, но иногда он может пригодиться для задания фокуса или измерения размеров, или положения дочернего DOM-узла.

Несмотря на то, что можно было бы добавить реф к дочернему компоненту, такое решение не является идеальным, т. к. вы получите экземпляр компонента вместо DOM-узла. Кроме того, это не сработает с функциональными компонентами.

Если вы работаете с React 16.3 или новее, мы рекомендуем использовать перенаправление рефов для таких случаев.

Перенаправление рефов позволяет компонентам осуществлять передачу рефа любого дочернего компонента как своего собственного. Вы можете найти детальные примеры того, как передать дочерний DOM-узел родительскому компоненту в документации по перенаправлению рефов.

Если вы используете React версии 16.2 или ниже, или если вам нужно решение более гибкое, чем перенаправление рефов, вы можете использовать данный альтернативный подход и явно передавать реф как проп с другим именем.

По возможности, мы советуем избегать передачи DOM-узлов, но это может быть полезной лазейкой. Заметим, что данный подход требует добавления кода в дочерний компонент. Если у вас нет никакого контроля над реализацией дочернего компонента, последним вариантом является использование

findDOMNode(), но такое решение не рекомендуется и не поддерживается в StrictMode.

Колбэк-рефы

Кроме того, React поддерживает другой способ определения рефов, который называется «колбэк-рефы» и предоставляет более полный контроль над их присвоением и сбросом.

Вместо того, чтобы передавать атрибут ref созданный с помощью createRef(), вы можете передать функцию. Данная функция получит экземпляр React-компонента или HTML DOM-элемент в качестве аргумента, которые потом могут быть сохранены или доступны в любом другом месте.

Представленный ниже пример реализует общий паттерн: использование колбэка в ref для хранения ссылки на DOM-узел в свойстве экземпляра.

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);

    this.textInput = null;
    this.setTextInputRef = element => {      this.textInput = element;    };
    this.focusTextInput = () => {            if (this.textInput) this.textInput.focus();    };  }

  componentDidMount() {
    
    this.focusTextInput();  }

  render() {
    
    
    return (
      <div>
        <input
          type="text"
          ref={this.setTextInputRef}        />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}        />
      </div>
    );
  }
}

React вызовет ref колбэк с DOM-элементом при монтировании компонента, а также вызовет его со значением null при размонтировании. Рефы будут хранить актуальное значение перед вызовом методов

componentDidMount или componentDidUpdate.

Вы можете передавать колбэк-рефы между компонентами точно так же, как и объектные рефы, созданные через React. createRef().

function CustomTextInput(props) {
  return (
    <div>
      <input ref={props.inputRef} />    </div>
  );
}

class Parent extends React.Component {
  render() {
    return (
      <CustomTextInput
        inputRef={el => this.inputElement = el}      />
    );
  }
}

В представленном выше примере, Parent передаёт свой колбэк-реф как проп inputRef компоненту CustomTextInput, а CustomTextInput передаёт ту же самую функцию как специальный атрибут ref элементу

<input>. В итоге свойство this.inputElement компонента Parent будет хранить значение DOM-узла, соответствующего элементу <input> в CustomTextInput.

Устаревший API: строковые рефы

Если вы уже работали с React ранее, возможно вы знакомы с более старым API, в котором атрибут ref является строкой, например"textInput", а DOM-узел доступен в this. refs.textInput. Мы не советуем пользоваться таким решением, т. к. у строковых рефов есть некоторые недостатки, они являются устаревшими и будут удалены в одном из будущих релизов.

Примечание

Если вы используете this.refs.textInput для доступа к рефам в своих проектах, мы рекомендуем перейти к использованию паттерна с колбэком или

createRef API.

Предостережения насчёт колбэк-рефов

Если ref колбэк определён как встроенная функция, колбэк будет вызван дважды во время обновлений: первый раз со значением null, а затем снова с DOM-элементом. Это связано с тем, что с каждым рендером создаётся новый экземпляр функции, поэтому React должен очистить старый реф и задать новый. Такого поведения можно избежать, если колбэк в ref будет определён с привязанным к классу контекстом, но, заметим, что это не будет играть роли в большинстве случаев.

HTML Ref Tag — это такая штука?



Я уверен, что сейчас почувствую себя абсолютно глупо, но разве там не должен быть тег ‘ref’? Я нигде не могу найти информацию об этом. То, что я ищу, — это тег, который можно использовать при цитировании/ссылках на материалы из внешних источников, таких как Википедия.

Спасибо!

html
Поделиться Источник jpppp     29 октября 2013 в 03:26

2 ответа


  • angular.element.cache, что это за штука?

    недавно я борюсь с ошибкой, которая angular не работает на странице. Я проверил это и обнаружил, что каким-то образом все свойства удалены из angular.element.cache Может ли кто-нибудь объяснить, что это за штука и по какой причине ее нужно очистить ?

  • Tag Helpers-Self closing HTML tags — это плохая привычка?

    Я включаю TagHelpers в свой проект MVC vNext, и я понял, что они не работают, когда я сам закрываю теги HTML. @addTagHelper *, Microsoft.AspNet.Mvc.TagHelpers <label asp-for=FirstName/> <!— self closing tag —> <span asp-validation-for=FirstName/> <!— self closing tag —>. ..



2

Да, она существует. Однако он называется <cite> .

Пример использования из MDN :

More information can be found in <cite>[ISO-0000]</cite>

Поделиться Brad     29 октября 2013 в 03:30


Поделиться A Fog     27 августа 2018 в 09:37


Похожие вопросы:


Что это за змееподобная длинная штука на ушах?

Я нашел это на веб-странице. Что это за длинная штука растет из этих ушей? Он встречается даже в исходном коде. Как это закодировано?…


git tag: fatal: не удалось разрешить ‘HEAD’ как действительный ref

Я клонирую одну ветвь из репозитория и создаю тег в скрипте python. Команды следующие. git clone -b master —single-branch <repository adress> git tag -a testag -m ‘test’ Он успешно. ..


Stray start tag html и head

Я новый программист, работающий на своем первом сайте RoR (с реализованной темой bootstrap) и имеющий некоторые (казалось бы, простые) проблемы с HTML, замеченные с проблемами обмена изображениями…


angular.element.cache, что это за штука?

недавно я борюсь с ошибкой, которая angular не работает на странице. Я проверил это и обнаружил, что каким-то образом все свойства удалены из angular.element.cache Может ли кто-нибудь объяснить, что…


Tag Helpers-Self closing HTML tags — это плохая привычка?

Я включаю TagHelpers в свой проект MVC vNext, и я понял, что они не работают, когда я сам закрываю теги HTML. @addTagHelper *, Microsoft.AspNet.Mvc.TagHelpers <label asp-for=FirstName/>…


git tag: fatal: не удалось разрешить ‘refs/remotes/my_tag_name’ как действительный ref

В настоящее время я клонирую РЕПО svn, которое имеет стандартную компоновку. В настоящее время он содержит код, соответствующий одному приложению iOS и одному приложению Android. Теги указывают,…


Событие Kotlinx-html ref

Я заметил следующую функцию в базе кода, которая использует kotlinx html , и ее довольно трудно полностью понять: private fun <E : HTMLElement> Tag.xrefImpl(prop: KMutableProperty0<E?>)…


Как отключить функцию зеркала VS Code auto-rename-tag / HTML?

Я хотел иметь возможность легко редактировать теги HTML вместе. Мне показалось, что это такая простая вещь для реализации в наши дни , поэтому я установил это расширение auto-rename-tag, и оно…


Как это исключено !Ref tag от check-yaml git hook?

Существует файл serverless.yaml , который содержит такую строку: VpcId: !Ref MyVpc Файлы Yaml проверяются крючком check-yaml git , который вызывается командой pre-commit . Таким образом, запуск…


Git pull невозможно обновить локальный ref

У меня есть что-то странное с тех пор, как мы начали использовать субмодули для git. Я нахожусь на Windows 10 и использую либо Tortoise git, либо Powershell, либо cmd, либо интерпретатор команд…

htmlreference.ru — Простой справочник по html

htmlreference.ru — Простой справочник по html

Простой справочник по html

a базовые строчные парные
abbr базовые строчные парные
address базовые блочные парные
area базовые строчные одинарные
aside семантические блочные парные
audio базовые блочные парные
b базовые строчные парные
base базовые одинарные
bdo базовые строчные парные
blockquote базовые блочные парные
body базовые блочные парные
br базовые строчные одинарные
button формы строчные парные
caption табличные блочные парные
cite семантические строчные парные
col табличные строчные одинарные
colgroup табличные строчные парные
datalist базовые блочные парные
dd списки строчные парные
del семантические строчные парные
details базовые блочные парные
dialog экспериментальные блочные парные
div базовые блочные парные
dl списки блочные парные
dt списки блочные парные
em базовые строчные парные
fieldset формы блочные парные
figcaption семантические блочные парные
figure семантические блочные парные
footer семантические блочные парные
h2 семантические блочные парные
h3 семантические блочные парные
h4 семантические блочные парные
h5 семантические блочные парные
h5 семантические блочные парные
head базовые блочные парные
header семантические блочные парные
hgroup семантические блочные парные
hr базовые блочные одинарные
i базовые строчные парные
iframe базовые блочные парные
img базовые строчные одинарные
input формы строчные одинарные

Последние изменения: 19. 10.2020, 21:17

Атрибуты HTML

Атрибут Принадлежит к Описание
принять <вход> Задает типы файлов, которые принимает сервер (только для type = «file»).
кодировка приема <форма> Задает кодировки символов, которые должны использоваться для формы. представление
ключ доступа Глобальные атрибуты Задает сочетание клавиш для активации / фокусировки элемента
действие <форма> Указывает, куда отправлять данные формы при отправке формы
выровнять Не поддерживается в HTML 5. Задает выравнивание по окружающим элементам. Используйте CSS вместо
alt , , Задает альтернативный текст, если исходный элемент не отображается.
асинхронный <сценарий> Указывает, что сценарий выполняется асинхронно (только для внешних скрипты)
автозаполнение <форма>, <ввод> Указывает, должен ли элемент
или иметь автозаполнение. включен
автофокус <кнопка>, ,