Эта статья используется для записи принципов React, которые я недавно изучил.Если есть какие-либо ошибки или неточности, пожалуйста, поправьте меня, большое спасибо. Если вам это нравится или у вас есть вдохновение, пожалуйста, поставьте лайк, это также поощрение автора. Если есть еще принципы, связанные с React, которые не были записаны, пожалуйста, оставьте сообщение для добавления, я буду продолжать обновлять. Спасибо 🙏
синтетическое событие
делегация мероприятия
Дополнительные события DOM см.Наггетс.Талант/пост/684790…
Давайте сначала поговорим о предварительном знании:делегация мероприятия. Делегирование событий использует восхождение событий, которое объединяет одну и ту же обработку событий дочерних элементов с родительскими элементами для унифицированной обработки. Пример 🌰: В следующем ul я хочу щелкнуть каждый тег li и распечатать содержимое тега li.
<ul id="poem">
<li>窗前明月光</li>
<li>疑似地上霜</li>
<li>举头望明月</li>
<li>低头思故乡</li>
</ul>
<script>
const liList = document.getElementsByTagName("li");
for(let i=0;i<liList.length;i++){
liList[i].addEventListener("click", function(e){
console.log(e.target.innerHTML);
})
}
</script>
Выше приведена грубая реализация. Используя делегирование событий, мы можем фактическиclick
Логика унифицирована в родительском элементеul
Вышеупомянутая обработка выглядит следующим образом:
const ul = document.getElementById("poem");
ul.addEventListener("click", function(e){
console.log(e.target.innerHTML);
})
синтетическое событие
Если вы все еще думаете, что написали<button onClick={this.addChange}>累加</button>
Было бы неправильно привязываться к нативной кнопке элемента DOM.
На самом деле печать напрямую addChange = (e)=>{ console.log(e); }
Просто знайте, что прототипом объекта e являетсяSyntheticEvent
класс вместоMouseEvent
объект.
React SyntheticEvent – это настраиваемый объект события, который React имитирует все возможности нативных событий DOM. Его можно понимать как кросс-браузерную оболочку для нативных событий браузера. Он определяет синтетические события в соответствии со спецификацией W3C, совместим со всеми браузерами и имеет тот же интерфейс, что и собственные события браузера.
Принцип синтеза событий заключается в использовании пузырькового всплытия событий посредствомделегация мероприятияУнифицируйте события на узле документа DOM.
Цель синтетических событий — кросс-браузерное выполнение для лучшей кросс-платформенной реализации. В то же время React вводит пул событий, чтобы избежать частой привязки и отвязки событий, что облегчает унифицированное управление событиями и механизм транзакций (механизм транзакций будет рассмотрен ниже).
Синтетические события React отличаются от нативных событий DOM, поэтому не смешивайте их. Синтез событий с помощью React
e.stopPropagation();
Не предотвращает появление нативных событий DOM.
class setStateDemo extends React.Component{
render(){
return <div>
<div onClick={this.clickDiv}>
<button onClick={this.addChange}>累加</button>
</div>
</div>
}
clickDiv = ()=>{
console.log("div clicked");
}
addChange = (e)=>{
e.stopPropagation();
console.log("btn clicked");
}
bodyClickHandler = (e)=>{
console.log("bodyClickHandler");
}
componentDidMount(){
document.body.addEventListener('click', this.bodyClickHandler);
}
componentWillUnmount(){
document.body.removeEventListener('click', this.bodyClickHandler)
}
}
Последний вопрос: события React и порядок выполнения нативных событий. Давайте поговорим о выводе непосредственно, вы можете написать код для его проверки:
- Все события React монтируются в объект документа;
- Когда реальный элемент DOM инициирует событие, он перейдет к объекту документа, а затем обработает событие React;
- Таким образом, сначала будет выполнено собственное событие, а затем будет обработано событие React;
- Наконец, событие, подключенное к документу, действительно выполняется.
zhuanlan.zhihu.com/p/25883536
у-у-у. Краткое описание.com/afraid/convenient 3199 ох 75…
blog.CSDN.net/QQ_36380426…
является ли setState синхронным или асинхронным
Давайте сначала перейдем к вопросу интервью, хахаха 🤣
class Test extends React.Component {
state = {
count: 0
};
componentDidMount() {
this.setState({count: this.state.count + 1});
console.log(this.state.count);
this.setState({count: this.state.count + 1});
console.log(this.state.count);
setTimeout(() => {
this.setState({count: this.state.count + 1});
console.log(this.state.count);
this.setState({count: this.state.count + 1});
console.log(this.state.count);
}, 0);
}
render() {
return null;
}
};
Каков результат вышеизложенного? Давайте сначала продадим здесь пропуск и продолжим смотреть вниз.
setState
Дизайн должен включать асинхронные обновления. Зачем объединять асинхронность? до и после, как указано вышеthis.setState({count: this.state.count + 1});
Выполняется дважды, если нет такого асинхронного механизма слияния, не будет ли страница обновляться дважды сразу. Дважды нормально, цикл for выполняет 10 000 или 100 000 операций присваивания, и страница не застрянет и не рухнет. такsetState
Вместо немедленного запуска обновления данных он сначала обновит этиsetState
Объедините их, подождите, пока «придет время», и выполните обновление. Когда "время пришло"? имеет переменнуюisBatchingUpdates
контролировать, обновлять ли значение состояния. Конкретная логика выглядит следующим образом:
setState
Следующая операция будет оцениваться в соответствии со значением isBatchingUpdates, если isBatchingUpdates истинно, сначалаsetState
Он кэшируется и не обновляется, когда isBatchingUpdates имеет значение false, он запускает обновление значения состояния и циклически обновляет все компоненты dirtyComponents.
React незаметно установил для isBatchingUpdates значение true, прежде чем синтезировать события и хуки жизненного цикла в React, что гарантирует слияниеsetState
во избежание частых срабатываний модификаций состояния, что приводит к частым перекомпоновкам и перерисовке страниц.
И дляsetTimeout、setInterval
выполнить вsetState
,setTimeout、setInterval
Это относится к задаче макроса. При выполнении связанных операций React завершил раунд ожидания, а isBatchingUpdates был изменен на false. В это времяsetState
Запустит прямую модификацию состояния.
С другой стороны, для нативных событий нет инкапсуляции и перехвата во внешнем слое React, а состояние isBatchingUpdates нельзя обновить до true. Это приводит к тому, что состояние isBatchingUpdates становится ложным и выполняется немедленно. Поэтому собственные события, такие как addEventListener, setTimeout и setInterval, будут обновляться синхронно.
дляsetState
Какова логика слияния? Вернемся к приведенным выше вопросам интервью, консоль будет выводить по очереди
0 0 2 3
Зачем?
this.setState({count: this.state.count + 1});
console.log(this.state.count);
this.setState({count: this.state.count + 1});
console.log(this.state.count);
существуетcomponentDidMount
Перед выполнением для isBatchingUpdates установлено значение true, затем выполняются первый проход и второй проход.this.setState({count: this.state.count + 1});
посетил, когдаthis.state.count
все равны 0, поэтому это эквивалентно выполнению:
this.setState({count: 1});
this.setState({count: 1});
Таким образом, он выведет 0 0
После этого дляsetTimeout
В функции мы знаем, что isBatchingUpdates уже имеет значение false, поэтому значение this.state.count будет немедленно изменено. Таким образом, он будет выводить 2 3 последовательно
не хочу объединяться
setState
Как это не "слиться"? Несколько раз это несколько раз, на самом деле, мы можем датьsetState
Передайте функцию и работайте на основе предыдущих данных каждый раз (чтобы убедиться, что получены самые последние данные), а неthis.state.count
Исходя из этого, посмотрите на код:
addFn = ()=>{
this.setState((prevState, props)=>{
return{
count: prevState.count + 1
}
});
this.setState((prevState, props)=>{
return{
count: prevState.count + 1
}
});
}
Что такое JSX
Что такое JSX? Что такое JSX? Что такое JSX? 😂 Душа просит три раза подряд.
JSX — это синтаксическое расширение JavaScript, очень близкое к языку шаблонов, но обладающее всеми возможностями JavaScript.
Выше приведено определение, данное на официальном сайте React. Мы можем говорить на простом языке: JSX — это синтаксическое расширение JavaScript, которое действует как шаблон, аналогичный шаблонам Vue.
JSX неотделим от экранирования Babel.Мы можем экранировать фрагмент кода JSX на официальном сайте Babel следующим образом:
Babel преобразует JSX в файл с именемReact.createElement()
вызов функции. Мы можем понять, что JSXReact.createElement()
функциональныйсинтаксический сахар. избегайте использования намиReact.createElement()
записыватьReact.createElement()
Различные параметры, требуемые функцией, синтаксис JSX показывает «шаблон», который мы хотим выразить общепринятым способом, с низкими затратами на обучение и с четкой структурой родительских и дочерних элементов.
React.createElement()
Что возвращает функция? это «элемент React», виртуальный DOM.
- Функция React.createElement(); отвечает за создание виртуального DOM «React Element».
- Функция ReactDOM.render(); отвечает за преобразование виртуального DOM в реальный DOM.
Почему компоненты класса связывают это
В компоненте класса, если мы не используем форму стрелочной функции, когда хотим привязать события к элементу, нам нужно добавить ее в конструкторthis.add = this.add.bind(this);
,правильноadd
Функция this привязана. Зачем?
class Counter extends React.Component{
constructor(props){
super(props);
this.state = { count: 0};
this.add = this.add.bind(this);
}
add(){
this.setState({
count: this.state.count + 1
});
}
render(){
return (
<div>
<button onClick={this.add}>普通 +1</button>
</div>
)
}
}
Для ES6, работающего в строгом режиме, в строгом режиме давайте сначала рассмотрим простую логику этого указателя:
"use strict";
function a(){
console.log(this);
}
a();
console.log(this);
В строгом режиме глобально это относится к окну; в функции это относится к неопределенному.
"use strict";
class Counter{
constructor(){
this.name = "Tom";
}
say(){
console.log(this);
}
}
const c = new Counter();
c.say();
const sayTmp = c.say;
sayTmp();
Вызовите метод say для экземпляра c счетчика, вы можете видеть, что это указывает на объект экземпляра c. ( Оператор new может изменить точку этогоНаггетс.Талант/пост/692309…Есть детали. )
Но мы присваиваем переменнуюsayTmp
, выполните, вы обнаружите, что это не определено. Это также ожидается. Функция sayTmp не указывает ни на какую переменную, поэтому она не определена.
Выше мы уже знаем, что JSX в конечном итоге будет экранирован какReact.createElement()
Вызов функции, создание виртуального DOM, а затем визуализация его на странице с помощью функции ReactDOM.render();. То есть компонент Counter будет экранирован следующим образом:
"use strict";
class Counter{
constructor(){
this.name = "Tom";
}
say(){
console.log(this);
}
render(){
createElement(this.say);
}
}
// 模拟 ReactDOM.render();
const createElement = function(cur){
const p = document.createElement("p");
p.innerHTML = "react dom";
p.addEventListener("click", function(){
cur();
});
document.body.append(p);
}
new Counter().render();
Когда мы нажимаем на элемент p на странице, выполняется событие связанного щелчка, а cur передается и выполняется, что эквивалентноconst cur = this.say;
.之后调用 cur 会发现 this 是 undefined。正因为此,需要在 Counter 的构造函数中对 this.say 绑定 this。
Жизненный цикл
Сначала придумайте относительно полный адрес диаграммы жизненного цикла React:проекты.Турк маджонг.Комментарии/react-life C...
Здесь мы представляем процесс жизненного цикла React после версии 16.4. Обычно используются componentDidMount, shouldComponentUpdate, componentDidUpdate, componentWillUnmount.
Всего имеется 8 связанных функций, а именно конструктор, getDerivedStateFromProps, render, componentDidMount, shouldCompopnentUpdate, getSnapshotBeforeUpdate, componentDidUpdate, componentWillUnmount.
горная сцена
Порядок выполнения такой: constructor getDerivedStateFromProps render componentDidMount
Представьте основную функцию: componentDidMount
componentDidMount
: Вызывается после загрузки компонента.В это время мы можем получать узлы DOM и работать, например, холст, операции svg, запросы к серверу и подписки. Не забудьте отписаться в componentWillUnmount.
этап обновления
Порядок выполнения такой:getDerivedStateFromProps shouldCompopnentUpdate render getSnapshotBeforeUpdate componentDidUpdate
Познакомить с основными функциями: shouldComponentUpdate, componentDidUpdate.
shouldComponentUpdate(nextProps, nextState):
Значение по умолчанию возвращает true. То есть это инициирует выполнение рендеринга и последующих функций жизненного цикла. Таким образом, по умолчанию изменение состояния родительского компонента приводит к тому, что дочерний компонент проходит через процесс обновления, даже если состояние родительского компонента не передается дочернему компоненту. Подкомпоненты рендерятся избыточно, мы можем использовать компонент PureComponent для оптимизации или вshouldComponentUpdate(nextProps, nextState)
Добавьте в функцию логику суждения, чтобы определить, стоит ли повторно отображать дочерний компонент.
componentDidUpdate(newProps, newState, Snapshot):
Функция, которая срабатывает после завершения обновления данных компонента, имеет следующие параметры:
newProps: новый реквизит
newState: новое состояние
Снимок: возвращенный getSnapshotBeforeUpdate
этап удаления
componentWillUnmount:
Она будет вызываться, когда наш компонент будет выгружен или уничтожен.Мы можем использовать эту функцию для очистки некоторых таймеров, отмены сетевых запросов, очистки недопустимых элементов DOM и другой работы по очистке мусора.
Почему некоторые жизненные циклы отбрасываются
Устаревшие функции жизненного цикла после React 16:
- componentWillMount
- componentWillReceviesProps
- componentWillUpdate
Эти функции жизненного цикла находятся на «этапе рендеринга» перед рендерингом,FiberПоявляются механизмы, позволяющие React приостановить, прервать или перезапустить этот этап. В то же время разработчики иногда выполняют некоторые операции в вышеперечисленных функциях, такие как отправка запросов, из-за чего эти запросы выполняются многократно. Чтобы избежать этих опасных операций, просто удалите эти избыточные функции жизненного цикла.
функциональный компонент
И функциональные компоненты, и компоненты классов в React — это методы реализации компонентов, которые мы часто используем. Внутри компонента функции нет состояния, и он часто используется как компонент пользовательского интерфейса, который используется только для рендеринга. Функциональные компоненты также известны как компоненты без состояния.
Для компонентов класса мы реализуем расширения React.Component со встроенными функциями, такими как жизненный цикл.Граница возможностей компонентов класса значительно сильнее, чем у функциональных компонентов.
Существует важное значение между двумя: функция захватывает состояние внутренних компонентов рендеринга, компоненты класса не будут; функциональные компоненты фактически делают данные и связывают вместе.
Отличная ранняя сравнительная статья автора React Дэна специально для компонентов классов и функций.слишком остро отреагировал.IO/как-женщины…Классический пример сравнения онлайн в статье:код sandbox.IO/is/with куда идти внутри 16…
Принцип React Hooks
Статьи с кратким руководством по React Hooks:Наггетс.Талант/пост/692715…
Хуки появились в React 16.8 впервые. Он позволяет вам использовать состояние и другие функции React без написания классов. Хуки не работают внутри класса. Но вы можете использовать их вместо class .
Что могут крючки?
- Использование состояния в функциональных компонентах (useState)
- Извлечь логику состояния компонента (пользовательский хук)
Начнем с правил использования React Hooks:
-
Используйте хуки только на верхнем уровнеНе вызывайте хуки в циклах, условных выражениях или вложенных функциях. Обязательно всегда вызывайте их на верхнем уровне вашей функции React, убедитесь, что хуки вызываются в одном и том же порядке при каждом рендеринге.
-
Вызывайте хуки только в функциях React, не вызывайте хуки в обычных функциях JavaScript.
По второму пункту хорошо понятно, что React-Hooks сам по себе является «крючком» React-компонентов, и внедрять его в обычные функции не имеет смысла. Почему хуки должны вызываться в одном и том же порядке при каждом рендере?
Проще говоря, React Hooks — это, по сути, функция, которая выполняется от начала до конца (от первой строки кода до последней строки кода) каждый раз, когда изменяется состояние.Нормальная работа хуков основана на последовательных связанных списках.Выполнение первого компонента функции React Hooks, несколькоuseState
а такжеuseEffect
Когда функция будет выполнена, она будет сохранена в связанном списке по порядку. Второй или n-й раз, когда функциональный компонент React Hooks выполняется,useState
а такжеuseEffect
При выполнении функции соответствующая информация будет по очереди проиндексирована из кэшированного связанного списка. если звонокuseState
а такжеuseEffect
Изменения в порядке (меньше или больше) приведут к некорректной информации в поиске по связанным спискам и ошибкам.
Если мы хотим выполнить эффект условно, мы можем поместить суждение внутри хука:
useEffect(function persistForm() {
// 👍 将条件判断放置在 effect 中
if (name !== '') {
localStorage.setItem('formData', name);
}
});
Рекомендуемый принцип React Hooks:GitHub.com/bricks pert/…
Fiber Reconciler
задний план:
Рабочий процесс React можно разделить на два этапа:
- Стадия согласования:React будет выполнять рекурсию сверху вниз, проходить новые данные для создания новой виртуальной модели DOM, а затем использовать алгоритм Diff для поиска элемента (исправления), который необходимо изменить, и помещать его в очередь обновлений.
- Стадия рендеринга (Renderer):Пройдите через очередь обновлений и фактически обновите и визуализируйте соответствующий элемент, вызвав API хост-среды. Среда хостинга, такая как DOM, Native, WebGL и т. д.
JavaScript однопоточный, а браузеры многопоточные. Поток JavaScript и поток рендеринга являются взаимоисключающими. Эти два потока не могут чередоваться и должны быть сериализованы. Пока один из потоков выполняется, другой поток может только приостанавливаться и ждать.
До React 16 на этапе координации из-за метода рекурсивного обхода это также называлось Stack Reconciler. У этого метода есть особенность: однажды запустив задачу, ее нельзя прервать, поэтому js всегда будет занимать основной поток, и не отдаст права на выполнение движку рендеринга, пока не будет просчитано все дерево Virtual DOM, тогда это приведет to Некоторые задачи, такие как взаимодействие с пользователем и анимация, не могут быть обработаны сразу, и будут задержки, которые сильно повлияют на пользовательский опыт.
Разбивая вопрос:
Fiber Reconciler, предложенный React 16, в основном предназначен для решения вышеуказанных проблем. Fiber реализует собственный стек вызовов компонентов, который обходит дерево компонентов в виде связанного списка, разбивает огромную задачу на маленькие задачи и может гибко приостанавливать, возобновлять и отбрасывать выполненные задачи.
Процесс обновления React Fiber разделен на две фазы (Phase):
- Фаза 1: сгенерируйте дерево волокон и получите информацию об узле, которую необходимо обновить. Этот шаг является постепенным процессом и может быть прерван.
- На втором этапе узлы, которые необходимо обновить, обновляются пакетно, и этот процесс нельзя прерывать.
Фаза 1 может быть прервана и перезапущена, а функции жизненного цикла этой фазы могут выполняться несколько раз. Так уж получилось, что разработчикcomponentWillMount、componentWillReceviesProps、getDerivedStateFromProps(nextProps,prevState)
Сделал что-то опасное, например отправил асинхронный запрос, что вызвало ошибку. Из-за этого в React 16 не рекомендуются 3 вышеуказанные функции жизненного цикла. Принцип реализации Fiber перекликается с разделом «Почему некоторые жизненные циклы заброшены» выше.