Сейчас (2018)react
Его становится все больше и больше 🔥 в сфере front-end разработки, да и сам я часто использую его в проектахreact
, но всегда интересноreact
Основополагающий принцип реализации , многие попытки прочитатьreact
Исходный код невозможно прочитать, это действительно слишком сложно. Не так давно я увидел в Интернете несколько статей, в которых рассказывалось, как сделать это своими руками.react
, основываясь на этих материалах и добавляя некоторые свои идеи, начиная с 0 только200
строка кода для реализации简版react
, я думаю, все будут правы после прочтенияreact
Узнайте больше о внутренней реализации . Но прежде чем мы это сделаем, нам нужно освоить несколькоreact
связанных важных понятий, таких как组件(类)
а также组件实例
разница,diff
алгоритм и生命周期
Подождите, давайте представим их по очереди, и мы их реализуем после того, как ознакомимся с этими понятиями.
1 Основные понятия: Component (компонент), instance (экземпляр компонента), element, jsx, dom
Прежде всего, нам нужно понять несколько запутанных концепций и начать изучатьreact
Меня также немного смутила разница между ними.Несколько дней назад я обсуждал проблему с новым одноклассником и обнаружил, что он не видит разницы.组件
а также组件实例
, поэтому необходимо понимать разницу между этими понятиями и связью, мы реализуем это позже в этой статье简版react
также основываются на этих понятиях.
Компонент
Component
Это компонент, который мы часто реализуем, который может быть类组件
(class component
)или函数式组件
(functional component
),а также类组件
Его можно разделить на компоненты общего класса (React.Component
) и компоненты чистого класса (React.PureComponent
), короче говоря, обе категории относятся к类组件
,ТолькоPureComponent
на основеshouldComponentUpdate
Сделаны некоторые оптимизации, которые здесь обсуждаться не будут.函数式组件
Он используется для упрощения реализации некоторых простых компонентов, используется для написания функции, а входными параметрами являются свойства компонента.props
, участвовать类组件
изrender
Возвращаемое значение метода такое же, какreact element
(Обратите внимание, что следующее введение уже появилось здесь.element
Ой).
Далее мы реализуем его тремя способами:Welcome
Компоненты:
// Component
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
// PureComponent
class Welcome extends React.PureComponent {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
// functional component
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
экземпляр (экземпляр компонента)
знакомый面向对象编程
конечно знаю类
а также实例
Отношения здесь такие же,组件实例
На самом деле组件类
В результате конкретизации концепция проста, но вreact
Здесь легко запутаться, почему вы так говорите? потому что всеreact
не создает экземпляр组件实例
, этот процесс на самом делеreact
Внутренне сделано для нас, поэтому мы действительно свяжемся组件实例
Возможностей не много. Мы больше подвержены следующимelement
, потому что мы обычно пишемjsx
На самом деле этоelement
Это просто представление (подробно описанное ниже). несмотря на то что组件实例
Я не использую его много, но я использую его иногда.ref
.ref
может указывать наdom节点
или类组件(class component)
, но не может использоваться для函数式组件
,потому что函数式组件
не можем实例化
. Вот краткое введениеref
, нам просто нужно знатьref
может указывать на组件实例
Вот и все, подробнее можно посмотретьreact
официальная документацияRefs and the DOM.
element
упомянутый ранееelement
,Прямо сейчас类组件
изrender
метод и函数式组件
Возвращаемое значениеelement
. тогда вотelement
что это такое? На самом деле очень просто, это чистый объект(plain object
), и этот чистый объект содержит два свойства:type:(string|ReactClass)
а такжеprops:Object
,Уведомлениеelement
нет组件实例
, а чистый объект.несмотря на то чтоelement
нет组件实例
, но он связан с экземпляром компонента,element
правда组件实例
илиdom节点
описание. еслиtype
даstring
типа, значитdom节点
,еслиtype
даfunction
илиclass
типа, значит组件实例
. Например, следующие дваelement
описатьdom节点
с одним组件实例
:
// 描述dom节点
{
type: 'button',
props: {
className: 'button button-blue',
children: {
type: 'b',
props: {
children: 'OK!'
}
}
}
}
function Button(props){
// ...
}
// 描述组件实例
{
type: Button,
props: {
color: 'blue',
children: 'OK!'
}
}
jsx
Просто разберисьelement
,Такjsx
Не трудно понять,jsx
Это просто другой способ написания, который нам удобно создаватьelement
Просто подумай, если нетjsx
Тогда эффективность нашей разработки определенно сильно снизится, а код определенно не будет способствовать сопровождению. Например, давайте посмотрим на следующееjsx
пример:
const foo = <div id="foo">Hello!</div>;
На самом деле, грубо говоря, он определяет узел domdiv
, а набор атрибутов для этого узла равен{id: 'foo'}
,children
даHello!
, именно такой объем информации, поэтому он полностью эквивалентен следующему чистому объектному представлению:
{
type: 'div',
props: {
id: 'foo',
children: 'Hello!'
}
}
ТакReact
как будетjsx
Как насчет преобразования синтаксиса в простые объекты? На самом деле, используяBabel
Скомпилировано и сгенерировано, нам нужно только использоватьjsx
добавить в код编译指示(pragma)
Да, вы можете обратиться сюдаКак Babel компилирует jsx. Например, мы будем编译指示
установить, чтобы указать наcreateElement
функция:/** @jsx createElement */
, то предыдущий абзацjsx
Код будет скомпилирован в:
var foo = createElement('div', {id:"foo"}, 'Hello!');
Как можно заметить,jsx
Процесс компиляции на самом деле из<
,>
это标签式
написать в函数调用式
Это просто преобразование правописания. С этой предпосылкой нам нужно просто реализовать следующееcreateElement
функция может быть построена безelement
Ну давай сами потом简版react
Также используйте эту функцию:
function createElement(type, props, ...children) {
props = Object.assign({}, props);
props.children = [].concat(...children)
.filter(child => child != null && child !== false)
.map(child => child instanceof Object ? child : createTextElement(child));
return {type, props};
}
dom
Мы также кратко представим здесь dom.Все, кто занимается исследованиями и разработками, должны быть знакомы с этой концепцией. Мы можем создать такой узел domdiv
:
const divDomNode = window.document.createElement('div');
На самом деле, все узлы domHTMLElement类
например, мы можем проверить следующее:
window.document.createElement('div') instanceof window.HTMLElement;
// 输出 true
оHTMLElement
API можно обратиться сюда:Введение в HTML-элемент. следовательно,dom
узелHTMLElement类
экземпляр; аналогично, вreact
в,组件实例
да组件类
экземпляр, в то время какelement
да снова组件实例
а такжеdom
Описание узла, взаимосвязь между этими понятиями теперь должны быть понятны всем. После введения этих основных понятий давайте нарисуем картинку, чтобы описать взаимосвязь между этими понятиями:
2 Виртуальный дом и алгоритм сравнения
считаю использованнымreact
Большинство студентов знакомы с этими двумя понятиями:虚拟dom
так же какdiff算法
. здесь虚拟dom
Собственно, об этом упоминалось ранееelement
, почему это虚拟
Что касается dom, мы уже представили его ранее.element
Толькоdom
узел или组件实例
Чистое объектное описаниеdom
узел, так оно и есть虚拟
дом.react
предоставил нам声明式
Способ написания компонента, когда компонентprops
илиstate
Компоненты автоматически обновляются при внесении изменений. Вся страница может фактически соответствовать одномуdom
дерево узлов, каждый компонентprops
илиstate
Изменения в первую очередь отражаются в虚拟dom
дерево, а затем, наконец, реагировать на страницуdom
Отрисовка дерева узлов.
Так虚拟dom
а такжеdiff算法
Что это значит? почему естьdiff
Алгоритмы на самом деле предназначены для улучшения渲染
Эффективность, представьте, если бы каждый компонентstate
илиprops
После изменения все соответствующиеdom
Если узел удаляется и создается заново, эффективность должна быть очень низкой, поэтому вreact
Есть два внутри虚拟dom
дерево соответственно现状
так же как下一个状态
,setState
срабатывает после звонкаdiff
выполнение алгоритма, а хорошееdiff
Алгоритм должен использоваться повторно как можно чаще.dom
узел, избегая накладных расходов на повторное создание. Я использую следующий рисунок для представления虚拟dom
а такжеdiff算法
Отношение:
react
Компонент генерируется первым после его первоначального отображения на странице.第1帧
виртуальный дом, на этот разcurrent指针
указывает на этот первый кадр.setState
будет сгенерировано после вызова第2帧
виртуальный дом, на этот разnext指针
указать на второй кадр, следующийdiff
алгоритм, сравнивая第2帧
а также第1帧
сходства и различия, чтобы применить обновление к реальномуdom
дерево, чтобы завершить обновление страницы.
Здесь еще раз подчеркиваетсяsetState
как генерировать虚拟dom
, потому что это важно и его легко игнорировать. Что только что было введено虚拟dom
Да, этоelement
Просто дерево. Этоelement
Как появилось дерево? На самом деле этоrender
Метод возвращается, следующая блок-схема усиливает впечатление:
react
официальная параdiff算法
Есть другое имя, всем точно будет вreact
Увидел в соответствующей информации, называемойReconciliation
, лично мне это слово кажется немного непонятным, но позже я перечитал словарь и обнаружил, что оно связано сdiff算法
Значение:можно увидетьreconcile
имеют消除分歧
,核对
значит, вreact
контраст в контексте虚拟dom
Смысл сходства и различия, по сути, состоит в том, чтобы сказатьdiff算法
. Здесь подчеркивается, что реализацию мы реализуем позже.reconcile
функция, состоит в том, чтобы реализоватьdiff
алгоритм.
3 Жизненный цикл и алгоритм сравнения
生命周期
а такжеdiff算法
Что это значит? Здесь мы беремcomponentDidMount
,componentWillUnmount
,ComponentWillUpdate
так же какcomponentDidUpdate
Возьмите пример, чтобы проиллюстрировать отношения между ними. мы знаем,setState
будет вызван после звонкаrender
генерировать новые虚拟dom
дерево, а это虚拟dom
Дерево может отличаться от предыдущего кадра следующим образом:
- Добавлен компонент;
- удалил компонент;
- Обновлены некоторые свойства компонента.
Поэтому мы реализуемdiff算法
Процесс будет вызывать их в соответствующем временном узле.生命周期
функция.
Здесь необходимо остановиться на упомянутом ранее第1帧
, мы знаем, что каждыйreact
Вход в приложение:
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
ReactDom.render
также будет генерировать虚拟dom
дерево, но это虚拟dom
Деревья рождаются из ниоткуда第一帧
, нет предыдущего кадра, используемого для сравнения, так что это虚拟dom
Все компоненты, соответствующие дереву, будут вызывать только挂载期
функции жизненного цикла, такие какcomponentDidMount
,componentWillUnmount
.
4 Реализация
Освоив понятия, введенные ранее, реализуйте简版react
Это не сложно. Здесь необходимо объяснить, что часть реализации этого раздела основана на реализации этого блога.Didact: a DIY guide to build your own React.
Теперь сначала посмотрим, какие API мы хотим реализовать. В итоге мы используем это следующим образом:
// 声明编译指示
/** @jsx DiyReact.createElement */
// 导入我们下面要实现的API
const DiyReact = importFromBelow();
// 业务代码
const randomLikes = () => Math.ceil(Math.random() * 100);
const stories = [
{name: "React", url: "https://reactjs.org/", likes: randomLikes()},
{name: "Node", url: "https://nodejs.org/en/", likes: randomLikes()},
{name: "Webpack", url: "https://webpack.js.org/", likes: randomLikes()}
];
const ItemRender = props => {
const {name, url} = props;
return (
<a href={url}>{name}</a>
);
};
class App extends DiyReact.Component {
render() {
return (
<div>
<h1>DiyReact Stories</h1>
<ul>
{this.props.stories.map(story => {
return <Story name={story.name} url={story.url} />;
})}
</ul>
</div>
);
}
componentWillMount() {
console.log('execute componentWillMount');
}
componentDidMount() {
console.log('execute componentDidMount');
}
componentWillUnmount() {
console.log('execute componentWillUnmount');
}
}
class Story extends DiyReact.Component {
constructor(props) {
super(props);
this.state = {likes: Math.ceil(Math.random() * 100)};
}
like() {
this.setState({
likes: this.state.likes + 1
});
}
render() {
const {name, url} = this.props;
const {likes} = this.state;
const likesElement = <span />;
return (
<li>
<button onClick={e => this.like()}>{likes}<b>❤️</b></button>
<ItemRender {...itemRenderProps} />
</li>
);
}
// shouldcomponentUpdate() {
// return true;
// }
componentWillUpdate() {
console.log('execute componentWillUpdate');
}
componentDidUpdate() {
console.log('execute componentDidUpdate');
}
}
// 将组件渲染到根dom节点
DiyReact.render(<App stories={stories} />, document.getElementById("root"));
Мы использовали в этом бизнес-кодеrender
,createElement
так же какComponent
Три API, поэтому следующая задача — реализовать эти три API и обернуть их в функцию.importFromBelow
внутри.
4.1 Реализовать createElement
createElement
функция сjsx
тесно связаны, как описано ранееjsx
Часть была введена, по сути, она похожа наhtml
Помеченное обозначение преобразуется в чистый объектelement
, конкретная реализация выглядит следующим образом:
function createElement(type, props, ...children) {
props = Object.assign({}, props);
props.children = [].concat(...children)
.filter(child => child != null && child !== false)
.map(child => child instanceof Object ? child : createTextElement(child));
return {type, props};
}
4.2 Рендеринг
обратите внимание на этоrender
эквивалентноReactDOM.render
,нет组件
изrender
метод,组件
изrender
метод позадиComponent
Часть реализации.
// rootInstance用来缓存一帧虚拟dom
let rootInstance = null;
function render(element, parentDom) {
// prevInstance指向前一帧
const prevInstance = rootInstance;
// element参数指向新生成的虚拟dom树
const nextInstance = reconcile(parentDom, prevInstance, element);
// 调用完reconcile算法(即diff算法)后将rooInstance指向最新一帧
rootInstance = nextInstance;
}
render
Реализация функции очень проста, всего два кадра虚拟dom
помириться, а потомrootInstance
указать на новый虚拟dom
. Если вы посмотрите внимательно, вы найдете новые虚拟dom
дляelement
, который вводится в началеelement
,а такжеreconcile
После虚拟dom
даinstance
, но этоinstance
нет组件实例
, посмотри сзадиinstantiate
реализация. во всяком случаеrender
На самом деле метод называетсяreconcile
метод для двух кадров虚拟dom
Просто сравнение.
4.3 Реализовать экземпляр
затем предыдущийinstance
в конце концовelement
Какая разница? фактическиinstance
Инструкция проста в том, чтобы положитьelement
Переупаковал слой и поставил соответствующийdom
Он тоже входит в комплектацию, в чем не сложно разобраться, ведь мы называемreconcile
провестиdiff
При сравнении нужно применять последние к реальнымdom
, поэтому необходимо следоватьdom
Связанная следующая реализацияinstantiate
Функция делает именно это. Обратите внимание, что из-заelement
включатьdom
тип иComponent
тип (поtype
Полевое суждение, если вы не понимаете, вы можете вернуться и посмотреть на первый разделelement
связанное введение), поэтому с ним нужно обращаться в зависимости от ситуации:
dom
Типelement.type
дляstring
тип, соответствующийinstance
Структура{element, dom, childInstances}
.
Component
Типelement.type
дляReactClass
тип, соответствующийinstance
Структура{dom, element, childInstance, publicInstance}
, обратите внимание на здесьpublicInstance
это было описано ранее组件实例
.
function instantiate(element) {
const {type, props = {}} = element;
const isDomElement = typeof type === 'string';
if (isDomElement) {
// 创建dom
const isTextElement = type === TEXT_ELEMENT;
const dom = isTextElement ? document.createTextNode('') : document.createElement(type);
// 设置dom的事件、数据属性
updateDomProperties(dom, [], element.props);
const children = props.children || [];
const childInstances = children.map(instantiate);
const childDoms = childInstances.map(childInstance => childInstance.dom);
childDoms.forEach(childDom => dom.appendChild(childDom));
const instance = {element, dom, childInstances};
return instance;
} else {
const instance = {};
const publicInstance = createPublicInstance(element, instance);
const childElement = publicInstance.render();
const childInstance = instantiate(childElement);
Object.assign(instance, {dom: childInstance.dom, element, childInstance, publicInstance});
return instance;
}
}
Обратите внимание, потому чтоdom节点
а также组件实例
могут иметь дочерние узлы, поэтомуinstantiate
В функции есть логика для рекурсивного создания экземпляров.
4.4 Отличие компонентов класса от функциональных компонентов
Как мы упоминали ранее, компоненты включают в себя类组件
(class component
)а также函数式组件
(functional component
). Я часто использую эти два типа компонентов в своей обычной работе.Если компонент используется только для рендеринга, я обычно использую函数式组件
, ведь логика кода проста, понятна и понятна. ТакReact
Как внутренне различить эти два компонента? Этот вопрос прост и прост, он сложен и сложен. Почему ты так говоришь, потому чтоReact
Внутренняя реализация действительно относительно проста, но эта простая реализация определяется после различных соображений. общее яйцо (Dan
) Есть статья, где подробно разбираетсяReact
Как различить два внутренне, я настоятельно рекомендую всем прочитать это, здесь я буду использовать его напрямую, ссылка на статью здесьHow Does React Tell a Class from a Function?. На самом деле ответ очень прост, мы добиваемся类组件
Обязательно нужно наследовать от классаReact.Component
, поэтому сначала дайтеReact.Component
Сделайте отметку, а затем оцените при создании экземпляра компонентаelement.type
Есть ли эта метка в цепочке прототипов .
// 打标记
Component.prototype.isReactComponent = {};
// 区分组件类型
const type = element.type;
const isDomElement = typeof type === 'string';
const isClassElement = !!(type.prototype && type.prototype.isReactComponent);
Здесь мы обновляем предыдущую функцию инстанцированияinstantiate
различать函数式组件
а также类组件
:
function instantiate(element) {
const {type, props = {}} = element;
const isDomElement = typeof type === 'string';
const isClassElement = !!(type.prototype && type.prototype.isReactComponent);
if (isDomElement) {
// 创建dom
const isTextElement = type === TEXT_ELEMENT;
const dom = isTextElement ? document.createTextNode('') : document.createElement(type);
// 设置dom的事件、数据属性
updateDomProperties(dom, [], element.props);
const children = props.children || [];
const childInstances = children.map(instantiate);
const childDoms = childInstances.map(childInstance => childInstance.dom);
childDoms.forEach(childDom => dom.appendChild(childDom));
const instance = {element, dom, childInstances};
return instance;
} else if (isClassElement) {
const instance = {};
const publicInstance = createPublicInstance(element, instance);
const childElement = publicInstance.render();
const childInstance = instantiate(childElement);
Object.assign(instance, {dom: childInstance.dom, element, childInstance, publicInstance});
return instance;
} else {
const childElement = type(element.props);
const childInstance = instantiate(childElement);
const instance = {
dom: childInstance.dom,
element,
childInstance,
fn: type
};
return instance;
}
}
Видно, что если это函数式组件
, мы не создавали экземпляр компонента, а напрямую вызывали функцию для получения虚拟dom
.
4.5 Реализовать согласование (алгоритм сравнения)
Вот в чем дело,reconcile
даreact
в основе, видимо, как только что поставилиstate
Быстрый рендеринг очень важен, поэтомуreact
Мы попытаемся повторно использовать существующие узлы вместо того, чтобы каждый раз динамически создавать все связанные узлы. ноreact
Сила этим не ограничивается,react16
Будуreconcile
алгоритм из предыдущегоstack
Архитектура была обновлена доfiber
Архитектура, дальнейшая оптимизация производительности.fiber
Соответствующее содержание будет представлено в следующем разделе.Для простоты и простоты понимания мы по-прежнему используем аналогичныеstack
Алгоритм архитектуры реализован, дляfiber
Теперь просто нужно знать его调度
Впринципе хватает конечно, будет время потом реализовать версию на базеfiber
архитектурный.
Сначала посмотри целикомreconcile
Поток обработки алгоритма:
- Если это добавлено
instance
, то вам нужно создать экземплярinstance
а такжеappendChild
; - Если это добавлено
instance
, но удалитьinstance
, то нужноremoveChild
; - Если ни добавить, ни удалить
instance
, то нужно посмотретьinstance
изtype
Независимо от того, изменяется ли он, если есть изменение, узел нельзя использовать повторно, и его необходимо создать.instance
,ПотомreplaceChild
; - если
type
Если изменений нет, можно повторно использовать существующую ноду, в этом случае необходимо судить, нативная ли она.dom
Node по-прежнему является нашей собственной реализацией.react
Node, эти два случая обрабатываются по-разному.
После понимания большого процесса нам нужно только выполнить его в нужное время.生命周期
Функции достаточно, смотрите конкретную реализацию ниже:
function reconcile(parentDom, instance, element) {
if (instance === null) {
const newInstance = instantiate(element);
// componentWillMount
newInstance.publicInstance
&& newInstance.publicInstance.componentWillMount
&& newInstance.publicInstance.componentWillMount();
parentDom.appendChild(newInstance.dom);
// componentDidMount
newInstance.publicInstance
&& newInstance.publicInstance.componentDidMount
&& newInstance.publicInstance.componentDidMount();
return newInstance;
} else if (element === null) {
// componentWillUnmount
instance.publicInstance
&& instance.publicInstance.componentWillUnmount
&& instance.publicInstance.componentWillUnmount();
parentDom.removeChild(instance.dom);
return null;
} else if (instance.element.type !== element.type) {
const newInstance = instantiate(element);
// componentDidMount
newInstance.publicInstance
&& newInstance.publicInstance.componentDidMount
&& newInstance.publicInstance.componentDidMount();
parentDom.replaceChild(newInstance.dom, instance.dom);
return newInstance;
} else if (typeof element.type === 'string') {
updateDomProperties(instance.dom, instance.element.props, element.props);
instance.childInstances = reconcileChildren(instance, element);
instance.element = element;
return instance;
} else {
if (instance.publicInstance
&& instance.publicInstance.shouldcomponentUpdate) {
if (!instance.publicInstance.shouldcomponentUpdate()) {
return;
}
}
// componentWillUpdate
instance.publicInstance
&& instance.publicInstance.componentWillUpdate
&& instance.publicInstance.componentWillUpdate();
instance.publicInstance.props = element.props;
let newChildElement;
if (instance.publicInstance) { // 类组件
instance.publicInstance.props = element.props;
newChildElement = instance.publicInstance.render();
} else { // 函数式组件
newChildElement = instance.fn(element.props);
}
const oldChildInstance = instance.childInstance;
const newChildInstance = reconcile(parentDom, oldChildInstance, newChildElement);
// componentDidUpdate
instance.publicInstance
&& instance.publicInstance.componentDidUpdate
&& instance.publicInstance.componentDidUpdate();
instance.dom = newChildInstance.dom;
instance.childInstance = newChildInstance;
instance.element = element;
return instance;
}
}
function reconcileChildren(instance, element) {
const {dom, childInstances} = instance;
const newChildElements = element.props.children || [];
const count = Math.max(childInstances.length, newChildElements.length);
const newChildInstances = [];
for (let i = 0; i < count; i++) {
newChildInstances[i] = reconcile(dom, childInstances[i], newChildElements[i]);
}
return newChildInstances.filter(instance => instance !== null);
}
прочитай этоreconcile
После алгоритма некоторым людям должно быть любопытно, почему этот алгоритм называетсяstack
Алгоритм кратко описан здесь. Как видно из предыдущей реализации, каждый раз, когда компонентstate
обновление вызоветreconcile
реализация, при этомreconcile
Выполнение также является рекурсивным процессом, и он не останавливается до тех пор, пока все узлы не будут выполнены рекурсивно в начале, поэтому он называетсяstack
алгоритм. Поскольку это рекурсивный процесс,diff
Как только алгоритм запущен, он должен быть выполнен, поэтому поток может быть заблокирован, а поскольку js является однопоточным, это может повлиять на ввод пользователя или частоту кадров рендеринга пользовательского интерфейса, уменьшая взаимодействие с пользователем. ноreact16
обновлен доfiber
Архитектура, эта проблема решена.
4.6 Общий код
Объединение всего этого кода из предыдущей реализации завершено.简版react
, меньше, чем200
Линейный код, так просто~! Посмотреть полный кодDiyReact.
5 Волоконная архитектура
react16
улучшенныйreconcile
Архитектура алгоритмов, отstack
обновитесь доfiber
Архитектура, о которой мы упоминали ранееstack
Недостаток архитектуры в том, что она реализована рекурсивно, после запуска ее нельзя поставить на паузу, и она может быть выполнена только за один раз. пользовательский опыт.
а такжеfiber
Архитектура другая. Нижний слой основан наrequestIdleCallback
планироватьdiff
Выполнение алгоритма, наrequestIdleCallback
Для введения, пожалуйста, обратитесь к моей предыдущей статье о js事件循环
статьяцикл событий javascript (сторона браузера, сторона узла).requestIdlecallback
Как следует из названия, функция состоит в том, чтобы использовать свободное время для выполнения задач. Обратите внимание здесь空闲时间
Это относительно задач с более высоким приоритетом (таких как пользовательский ввод, рендеринг пользовательского интерфейса).
Вот краткое введениеfiber
Происхождение названия, потому что мне сначала было любопытно, почему оно так называетсяfiber
.fiber
Фактически纤程
Значение не новое слово, можно посмотреть объяснение ВикипедииFiber (computer science). На самом деле, я хочу выразить更加精细粒度的调度
смысл, потому что на основе этого алгоритмаreact
Можно поставить на паузу в любой моментdiff
Выполнение алгоритма, а потом есть время простоя на его выполнение, что более精细
Поэтому алгоритм планирования называетсяfiber
Архитектура. Эта статья правильнаяfiber
Сначала я кратко представлю их, а затем, когда будет время, резюмирую их по отдельности.
6 ссылок
В основном обратитесь к следующей информации: