Вопросы о событиях React
-
1. Почему ручная привязка
this -
2.
ReactВ чем разница между событием и нативным событием -
3.
ReactМожно ли смешивать порядок выполнения событий и собственных событий? -
4.
ReactКак события разрешают кросс-браузерную совместимость -
5. Что такое синтетическое событие
Ниже приведена блок-схема, которая обобщает все процессы выполнения после того, как я прочитал исходный код. Я не буду вставлять код. Если вы хотите прочитать код, чтобы увидеть, как он реализован, вы можете найти его в исходном коде в соответствии с блок-схема.
регистрация на мероприятие

- Загрузка/обновление компонента.
- пройти через
lastProps,nextPropsЧтобы определить, следует ли добавлять или удалять события, вызовите методы регистрации и удаления событий соответственно. - перечислить
EventPluginHubизenqueuePutListenerдля хранения событий - Получать
documentобъект. - По названию события (например,
onClick,onCaptureClick), чтобы определить, следует ли всплывать или захватывать. - определить, есть ли
addEventListenerметод, в противном случае используйтеattachEvent(совместимо с IE). - давать
documentЗарегистрируйте обратный вызов собственного события какdispatchEvent(унифицированный механизм распределения событий).
хранилище событий

-
EventPluginHubОтвечает за управление синтетическими событиями React.callback, будетcallbackсохранить вlistenerBank, а также сохраняетPlugin. -
EventPluginHubизputListenerМетод заключается в добавлении прослушивателя в контейнер хранилища. - Получить уникальный идентификатор элемента, привязанного к событию
key. - будет
callbackУникальная идентификация элемента на основе типа событияkeyсохранить вlistenerBankсередина. -
listenerBankСтруктура:listenerBank[registrationName][key].
Например:
{
onClick:{
nodeid1:()=>{...}
nodeid2:()=>{...}
},
onChange:{
nodeid3:()=>{...}
nodeid4:()=>{...}
}
}
Запуск/выполнение события

Выполнение события здесь используетReactМеханизм пакетной обработки из предыдущей статьи[Подробно реагировать] механизм выполнения setStateОн уже был проанализирован в , и не будет здесь более подробно анализироваться.
- курок
documentРегистрация обратных вызовов для нативных событийdispatchEvent - Получить элемент, который запускает событие на самом глубоком уровне
Например, следующий код: first получитthis.child
<div onClick={this.parentClick} ref={ref => this.parent = ref}>
<div onClick={this.childClick} ref={ref => this.child = ref}>
test
</div>
</div>
- Пройдите все родительские элементы этого элемента и обработайте каждый уровень элементов по очереди.
- Создайте синтетическое событие.
- Сохраните синтетические события на каждом уровне в
eventQueueв очереди событий. - траверс
eventQueue. - пройти через
isPropagationStoppedОпределяет, выполняет ли текущее событие метод предотвращения всплытия. - Если всплытие предотвращено, остановите обход, в противном случае пропустите
executeDispatchВыполнение синтетических событий. - Отпустите событие о завершении обработки.
reactПереопределено в собственном синтетическом событииstopPropagationметод, будетisPropagationStoppedУстановить какtrue, а затем решить, продолжать ли выполнение в соответствии с этим обходом в процессе обхода каждого уровня событий. ЭтоreactСамореализованный барботажный механизм.
синтетическое событие

- перечислить
EventPluginHubизextractEventsметод. - перебрать все типы
EventPlugin(служебные методы для обработки различных событий). - в каждом
EventPluginВозвращает разные пулы событий в соответствии с разными типами событий. - Извлеките синтетическое событие из пула событий и создайте новое, если пул событий пуст.
- по элементу
nodeid(Уникально идентифицируетkey) и тип события изlistenerBinkУберите функцию обратного вызова - Возвращает функцию обратного вызова с синтетическими параметрами события.
Общий процесс
Соедините вышеуказанные четыре процесса последовательно.

Зачем вручную привязывать это
Благодаря анализу процессов, запускаемому событиями,dispatchEventназываетсяinvokeGuardedCallbackметод.
function invokeGuardedCallback(name, func, a) {
try {
func(a);
} catch (x) {
if (caughtError === null) {
caughtError = x;
}
}
}
Видно, что callback-функция вызывается напрямую, а вызываемый компонент не указывается, поэтому он получается напрямую без ручной привязки.thisдаundefined.
Здесь можно использовать экспериментальныйсинтаксис инициализации свойства, то есть стрелочная функция объявлена прямо в компоненте. Стрелочные функции не создают свои собственныеthis, он будет наследоваться только от одного уровня выше своей собственной цепочки областей видимости.this. Поэтому мыReactВ событии получается сам компонент.
Чем оно отличается от исходного события?
-
ReactСобытия названы верблюжьим регистром, а не строчными. -
пройти через
JSX, вы передаете функцию в качестве обработчика события, а не строку.
Например,HTML:
<button onclick="activateLasers()">
Activate Lasers
</button>
существуетReactнемного отличается:
<button onClick={activateLasers}>
Activate Lasers
</button>
Еще одно отличие состоит в том, что в React нельзя вернутьfalseчтобы предотвратить поведение по умолчанию. нужно вызывать явноpreventDefault.
Из приведенного выше механизма выполнения мы можем извлечь:ReactОн реализовал набор механизмов событий, смоделировал процесс всплытия и захвата событий, принял прокси-сервер событий, пакетное обновление и другие методы, а также сгладил проблемы совместимости различных браузеров.
ReactПорядок выполнения событий и собственных событий
componentDidMount() {
this.parent.addEventListener('click', (e) => {
console.log('dom parent');
})
this.child.addEventListener('click', (e) => {
console.log('dom child');
})
document.addEventListener('click', (e) => {
console.log('document');
})
}
childClick = (e) => {
console.log('react child');
}
parentClick = (e) => {
console.log('react parent');
}
render() {
return (
<div onClick={this.parentClick} ref={ref => this.parent = ref}>
<div onClick={this.childClick} ref={ref => this.child = ref}>
test
</div>
</div>)
}
Результаты:
Из описанного выше процесса мы можем понять:
-
reactВсе события смонтированы наdocumentсередина - Когда срабатывает настоящий дом, он пузырится до
documentпозжеreactобработка событий - Таким образом, собственное событие будет выполнено первым
- затем выполнить
reactсинтетическое событие - Окончательное исполнение действительно в
documentсобытия, установленные на
Можно ли смешивать реагирующие события и нативные события?
reactЛучше не смешивать события и нативные события.
Если выполняется в нативном событииstopPropagationметод, приведет к другимreactНедействительность события. потому что события для всех элементов не смогут всплывать доdocumentначальство.
Из приведенного выше механизма выполнения несложно сделать вывод, что все события реакции не смогут быть зарегистрированы.
Синтетические события, совместимые с браузером
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
здесь,
eявляется составным событием.Reactв соответствии с W3C Спецификация определяет это синтетическое событие, так что вам не нужно беспокоиться о кросс-браузерной совместимости.
Обработчик события доставитSyntheticEvent, который представляет собой встроенную кросс-браузерную оболочку событий. Он имеет тот же интерфейс, что и собственные события браузера, в том числеstopPropagation()иpreventDefault(), они работают одинаково во всех браузерах.
каждыйSyntheticEventВсе объекты имеют следующие свойства:
boolean bubbles
boolean cancelable
DOMEventTarget currentTarget
boolean defaultPrevented
number eventPhase
boolean isTrusted
DOMEvent nativeEvent
void preventDefault()
boolean isDefaultPrevented()
void stopPropagation()
boolean isPropagationStopped()
DOMEventTarget target
number timeStamp
string type
ReactСинтетическийSyntheticEventИспользуется пул событий, который может значительно сэкономить память без частого создания и уничтожения объектов событий.
Кроме того, независимо от того, какая среда браузера используется, браузер будет единообразно создавать тип события как синтетическое событие, чтобы достичь цели совместимости браузера.