Fibers root

Техника

Погрузитесь глубоко в новую архитектуру React под названием Fiber и узнайте о двух основных фазах нового алгоритма согласования (reconciliation). Мы подробно рассмотрим, как React обновляет состояние и пропсы и обрабатывает дочерние элементы.


React — это JavaScript библиотека для создания пользовательских интерфейсов. В ее основе лежит механизм, который отслеживает изменения в состоянии компонента и проецирует обновленное состояние на экран. В React мы знаем этот процесс как согласование (reconciliation). Мы вызываем метод setState, фреймворк проверяет, изменилось ли состояние или пропс, и перерендеривает компонент в UI.

Документация React предоставляет хороший высокоуровневый обзор механизма: роль элементов React, методы жизненного цикла и метод render, а также алгоритм диффиринга (сравнения, diffing), применяемый к дочерним элементам компонента. Дерево иммутабельных элементов React, возвращаемых методом render, обычно называют «виртуальный DOM». Этот термин помог объяснить React людям в самом начале, но он также вызвал путаницу и больше не используется в документации по React. В этой статье я буду называть его деревом React-элементов.

Помимо дерева React-элементов, фреймворк всегда имел дерево внутренних экземпляров (компонентов, узлов DOM и т.д.), используемых для хранения состояния. Начиная с версии 16, React развернул новую реализацию этого дерева внутренних экземпляров и алгоритма, который управляет им, под кодовым названием Fiber. Чтобы узнать о преимуществах архитектуры Fiber, ознакомьтесь с The how and why on React’s use of linked list in Fiber.

Это первая статья из цикла, цель которого — научить вас внутренней архитектуре React. В этой статье я хочу предоставить углубленный обзор важных концепций и структур данных, имеющих отношение к алгоритму. Как только мы получим достаточную базу, мы изучим алгоритм и основные функции, используемые для обхода и обработки fiber-дерева. В следующих статьях цикла будет показано, как React использует алгоритм для выполнения начального рендеринга и обработки обновлений состояния и пропсов. Далее мы перейдем к деталям планировщика, процессу согласования (reconciliation) дочерних элементов и механизму построения списка эффектов.

Здесь я собираюсь дать вам довольно продвинутые знания. Я рекомендую вам прочитать ее, чтобы понять магию, скрывающуюся за внутренними механизмами Concurrent React. Эта серия статей также послужит вам отличным руководством, если вы планируете начать вносить свой вклад в React. Я сильно верю в реверс-инжиниринг, поэтому здесь будет много ссылок на исходники недавней версии 16.6.0.

Это, безусловно, довольно много, так что не переживайте, если вы не поймете что-то сразу. Это займет время, как и все стоящее. Обратите внимание, что вам не нужно знать ничего из этого, чтобы использовать React. Эта статья о том, как React работает внутри.

Базовый бэкграунд

Вот простое приложение, которое я буду использовать на протяжении всей серии. У нас есть кнопка, которая просто увеличивает число, отображаемое на экране:

А вот и реализация:

class ClickCounter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {count: 0};
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
        this.setState((state) => {
            return {count: state.count + 1};
        });
    }

    render() {
        return [
            <button key="1" onClick={this.handleClick}>Update counter</button>,
            <span key="2">{this.state.count}</span>;
        ]
    }
}

Вы можете поиграть с ним здесь. Как вы можете видеть, это простой компонент, который возвращает два дочерних элемента button и span из метода render. Как только вы нажимаете на кнопку, состояние компонента обновляется внутри обработчика. Это, в свою очередь, приводит к обновлению текста элемента span.

Во время согласования (reconciliation) React выполняет различные действия. Например, вот операции высокого уровня, которые React выполняет во время первого рендеринга и после обновления состояния в нашем простом приложении:

  • обновляет свойство count в state в ClickCounter.

  • извлекает и сравнивает дочерние элементы ClickCounter и их пропсы

  • обновляет пропсы элемента span

Есть и другие действия, выполняемые во время согласования, такие как вызов методов жизненного цикла или обновление refsВсе эти действия в совокупности называются «работой» (work) в архитектуре Fiber. Тип работы обычно зависит от типа элемента React. Например, для классового компонента React должен создать экземпляр, в то время как для функционального компонента он этого не делает. Как вы знаете, в React есть много видов элементов, например, классовые и функциональные компоненты, компоненты-хосты (DOM узлы), порталы и т. д. Тип элемента React определяется первым параметром функции createElement. Эта функция обычно используется в методе render для создания элемента.

Прежде чем приступить к изучению действий и основного fiber алгоритма, давайте сначала познакомимся со структурами данных, используемыми внутри React.

От React-элементов к Fiber-узлам

Каждый компонент в React имеет UI-представление, которое мы можем назвать представлением или шаблоном, возвращаемым методом render. Вот шаблон для нашего компонента ClickCounter:

<button key="1" onClick={this.onClick}>Update counter</button>
<span key="2">{this.state.count}</span>

React-элементы

Когда шаблон проходит через JSX-компилятор, в итоге вы получаете набор React-элементов. Это то, что действительно возвращается из метода render компонентов React, а не HTML. Поскольку от нас не требуется обязательно использовать JSX, метод render для нашего компонента ClickCounter можно переписать следующим образом:

class ClickCounter {
    ...
    render() {
        return [
            React.createElement(
                'button',
                {
                    key: '1',
                    onClick: this.onClick
                },
                'Update counter'
            ),
            React.createElement(
                'span',
                {
                    key: '2'
                },
                this.state.count
            )
        ]
    }
}

Вызовы React.createElement в методе render создадут две структуры данных:

[
    {
        $$typeof: Symbol(react.element),
        type: 'button',
        key: "1",
        props: {
            children: 'Update counter',
            onClick: () => { ... }
        }
    },
    {
        $$typeof: Symbol(react.element),
        type: 'span',
        key: "2",
        props: {
            children: 0
        }
    }
]

Вы можете видеть, что React добавляет свойство $$typeof к этим объектам, чтобы однозначно идентифицировать их как React элементы. Затем у нас есть свойства type, key и props, которые описывают элемент. Значения берутся из того, что вы передаете в функцию React.createElement. Обратите внимание, как React представляет текстовое содержимое в качестве дочерних элементов узлов span и button. А обработчик клика является частью пропсов элемента button. Существуют и другие поля в элементах React, например, поле ref, которые выходят за рамки этой статьи.

У элемента React созданного для ClickCounter нет ни пропсов, ни ключа:

{
    $$typeof: Symbol(react.element),
    key: null,
    props: {},
    ref: null,
    type: ClickCounter
}

Fiber-узлы

Во время согласования (reconciliation) данные каждого React элемента, возвращенные из метода render, объединяются в дерево fiber-узлов. Каждый React элемент имеет соответствующий fiber-узел. В отличие от React элементов, fibers не создаются заново при каждом рендере. Это мутабельные структуры данных, которые хранят состояние компонентов и DOM.

Ранее мы обсуждали, что в зависимости от типа React элемента фреймворк должен выполнять различные действия. В нашем примере приложения для классового компонента ClickCounter он вызывает методы жизненного цикла и метод render, в то время как для хост-компонента span (DOM узел) он выполняет мутацию DOM. Таким образом, каждый элемент React преобразуется в Fiber-узел соответствующего типа, который описывает работу, которую необходимо выполнить.

Вы можете думать о Fiber как о структуре данных, которая представляет некоторую работу, которую нужно выполнить, или, другими словами, единицу работы. Архитектура Fiber также обеспечивает удобный способ отслеживания, планирования, приостановки и прерывания работы.

Когда элемент React впервые преобразуется в fiber-узел, React использует данные из элемента для создания fiber в функции createFiberFromTypeAndProps. При последующих обновлениях React повторно использует fiber-узел и просто обновляет необходимые свойства, используя данные из соответствующего React-элемента. React также может потребоваться переместить узел в иерархии на основе пропсов key или удалить его, если соответствующий элемент React больше не возвращается из метода render.

Посмотрите функцию ChildReconciler, чтобы увидеть список всех действий и соответствующих функций, которые React выполняет для существующих fiber-узлов.

Поскольку React создает fiber для каждого React элемента, и поскольку у нас есть дерево этих элементов, у нас будет дерево fiber-узлов. В случае с нашим примером приложения это выглядит следующим образом:

Все fiber-узлы связаны между собой через связный список (linked list), используя следующие свойства fiber-узлов: child, sibling и return. Более подробно о том, почему это работает именно так, читайте в моей статье The how and why on React’s use of linked list in Fiber, если вы еще не читали ее.

Текущее (current) дерево и work in progress дерево

После первого рендеринга React заканчивает работу с fiber-деревом, которое отражает состояние приложения, использованного для отрисовки пользовательского интерфейса. Это дерево часто называют текущим (current). Когда React начинает работать над обновлениями, он строит так называемое workInProgress дерево, которое отражает будущее состояние, которое будет выведено на экран.

Вся работа выполняется над fibers из дерева workInProgress. Когда React проходит через текущее дерево, для каждого существующего fiber-узла он создает альтернативный узел, который составляет workInProgressдерево. Этот узел создается с использованием данных из элементов React, возвращаемых методом render. Как только обновления будут обработаны и вся связанная с ними работа будет завершена, React получит альтернативное дерево, готовое к выводу на экран. Как только это workInProgress дерево будет выведено на экран, оно станет текущим деревом.

Один из основных принципов React — последовательность. React всегда обновляет DOM за один раз — он не показывает частичные результаты. Дерево workInProgress служит в качестве «черновика», который не виден пользователю, чтобы React мог сначала обработать все компоненты, а затем вывести их изменения на экран.

В исходных текстах вы увидите множество функций, которые берут fiber-узлы из обоих деревьев current и workInProgress. Вот сигнатура одной из таких функций:

function updateHostComponent(current, workInProgress, renderExpirationTime) {...}

Каждый fiber-узел содержит ссылку на свой аналог из другого дерева в поле alternate. Узел из текущего дерева указывает на узел из дерева workInProgress и наоборот.

Побочные эффекты (Side-effects)

Мы можем думать о компоненте в React как о функции, которая использует состояние и пропсы для вычисления UI-представления. Любые другие действия, такие как мутирование DOM или вызов методов жизненного цикла, следует рассматривать как побочный эффект или, просто, эффект. Эффекты также упоминаются в документации:

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

Вы можете видеть, как большинство обновлений состояния и пропсов приводят к побочным эффектам. А поскольку применение эффектов — это один из видов работы, узел fiber — это удобный механизм для отслеживания эффектов в дополнение к обновлениям. Каждый узел волокна может иметь эффекты, связанные с ним. Они кодируются в поле effectTag.

Таким образом, эффекты в Fiber в основном определяют работу, которую необходимо выполнить для экземпляров после обработки обновлений. Для хост компонентов (DOM элементов) работа заключается в добавлении, обновлении или удалении элементов. Для классовых компонентов React может потребоваться обновление refs и вызов методов жизненного цикла componentDidMount и componentDidUpdate. Существуют также другие эффекты, соответствующие другим типам fiber-ов.

Список эффектов (effects list)

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

Цель этого списка — пометить узлы, которые имеют DOM обновления или другие эффекты, связанные с ними. Этот список является подмножеством дерева finishedWork и связан посредством свойства nextEffect вместо свойства child, используемого в деревьях current и workInProgress.

Dan Abramov предложил аналогию для списка эффектов. Ему нравится думать о нем как о рождественской елке, с «рождественскими огнями», связывающими все узлы эффектов вместе. Чтобы визуализировать это, давайте представим следующее дерево из fiber-узлов, где выделенные узлы выполняют определенную работу. Например, в результате нашего обновления c2 был вставлен в DOM, d2 и c1 изменили атрибуты, а b2 запустил метод жизненного цикла. Список эффектов свяжет их вместе, чтобы React мог пропустить другие узлы позже:

Дополнительно:  Пропал звук на ноутбуке: что делать

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

Корень fiber-дерева

В каждом React-приложении есть один или несколько элементов DOM, которые выступают в качестве контейнеров. В нашем случае это элемент div с ID container.

const domContainer = document.querySelector('#container');
ReactDOM.render(React.createElement(ClickCounter), domContainer);

React создает объект fiber root для каждого из этих контейнеров. Вы можете получить к нему доступ, используя ссылку на DOM элемент:

const fiberRoot = query('#container')._reactRootContainer._internalRoot

Этот fiber root является местом, где React хранит ссылку на fiber tree. Она хранится в свойстве current fiber root:

const hostRootFiberNode = fiberRoot.current

Fiber-дерево начинается со специального типа fiber-узла, которым является HostRoot. Он создается внутри и действует как родитель для вашего самого верхнего компонента. Существует связь от fiber-узла HostRoot обратно к FiberRoot через свойство stateNode:

fiberRoot.current.stateNode === fiberRoot; // true

Вы можете изучить fiber-дерево, обратившись к самому верхнему fiber-узлу HostRoot через fiber root. Или вы можете получить отдельный fiber-узел из экземпляра компонента следующим образом:

compInstance._reactInternalFiber

Структура fiber-узла

Теперь рассмотрим структуру fiber-узлов, созданных для компонента ClickCounter:

{
    stateNode: new ClickCounter,
    type: ClickCounter,
    alternate: null,
    key: null,
    updateQueue: null,
    memoizedState: {count: 0},
    pendingProps: {},
    memoizedProps: {},
    tag: 1,
    effectTag: 0,
    nextEffect: null
}

и DOM-элемента span:

{
    stateNode: new HTMLSpanElement,
    type: "span",
    alternate: null,
    key: "2",
    updateQueue: null,
    memoizedState: null,
    pendingProps: {children: 0},
    memoizedProps: {children: 0},
    tag: 5,
    effectTag: 0,
    nextEffect: null
}

В fiber-узлах довольно много полей. Я описал назначение полей alternate, effectTag и nextEffect в предыдущих разделах. Теперь давайте посмотрим, зачем нам нужны другие.

stateNode

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

type

Определяет функцию или класс, связанный с этим fiber. Для классовых компонентов оно указывает на функцию-конструктор, а для DOM элементов — на HTML-тег. Я довольно часто использую это поле, чтобы понять, с каким элементом связан fiber-узел.

tag

Определяет тип fiber. Он используется в алгоритме согласования (reconciliation), чтобы определить, какую работу нужно выполнить. Как упоминалось ранее, работа варьируется в зависимости от типа React элемента. Функция createFiberFromTypeAndProps сопоставляет элемент React с соответствующим типом fiber-узла. В нашем приложении свойство tag для компонента ClickCounter равно 1, что обозначает ClassComponent, а для элемента span5, что обозначает HostComponent.

updateQueue

Очередь обновлений состояния, обратных вызовов и обновлений DOM.

memoizedState

Состояние fiber-a, которое было использовано для создания вывода. При обработке обновлений оно отражает состояние, которое в данный момент выводится на экран.

memoizedProps

Пропсы fiber-а, которые были использованы для создания вывода во время предыдущего рендера.

pendingProps

Пропсы, которые были обновлены на основе новых данных в React элементах и должны быть применены к дочерним компонентам или DOM элементам.

key

Уникальный идентификатор с группой дочерних элементов, помогающий React выяснить, какие элементы изменились, были добавлены или удалены из списка. Это связано с функциональностью «списки и ключи» React, описанным здесь.

Полную структуру fiber-узла можно найти здесь. В приведенном выше объяснении я пропустил кучу полей. В частности, я пропустил указатели child, sibling и return, составляющие древовидную структуру данных, которую я описал в своей предыдущей статье. И пропустил категорию полей, таких как expirationTime, childExpirationTime и mode, которые специфичны для Scheduler.

Итоговый алгоритм

React выполняет работу в двух основных фазах: render и commit.

Во время первой фазы render React применяет обновления к компонентам, запланированные через setState или React.render, и выясняет, что нужно обновить в пользовательском интерфейсе. Если это первоначальный рендеринг, React создает новый fiber-узел для каждого элемента, возвращенного из метода render. При последующих обновлениях fiber-ы для существующих React элементов используются повторно и обновляются. Результатом фазы является дерево fiber-узлов, помеченных побочными эффектами. Эффекты описывают работу, которая должна быть выполнена во время следующей фазы commit. Во время этой фазы React берет fiber-дерево, помеченное эффектами, и применяет их к экземплярам. Он просматривает список эффектов и выполняет обновления DOM и другие изменения, видимые пользователю.

Важно понимать, что работа во время первой render фазы может выполняться асинхронно. React может обработать один или несколько fiber-узлов в зависимости от доступного времени, затем остановиться, чтобы сохранить проделанную работу и уступить какому-либо событию. Затем он продолжает работу с того места, где остановился. Иногда, однако, может потребоваться отбросить проделанную работу и начать все сначала. Такие паузы возможны благодаря тому, что работа, выполняемая в этой фазе, не приводит к каким-либо видимым пользователю изменениям, таким как обновление DOM. В отличие от этого, следующая commit фаза всегда синхронна. Это происходит потому, что работа, выполняемая на этом этапе, приводит к изменениям, видимым пользователю, например, к обновлению DOM. Поэтому React должен выполнять её за один проход.

Вызов методов жизненного цикла — это один из видов работы, выполняемой React. Некоторые методы вызываются на этапе render, а другие — на этапе commit. Вот список методов жизненного цикла, вызываемых при выполнении первой фазы render:

Как вы можете видеть, некоторые устаревшие методы жизненного цикла, выполняемые на этапе render, помечены как UNSAFE с версии 16.3. В документации они теперь называются legacy lifecycles. Они будут устаревшими в будущих релизах 16.x, а их аналоги без префикса UNSAFE будут удалены в версии 17.0. Подробнее об этих изменениях и предлагаемом пути миграции вы можете прочитать здесь.

Вам интересно узнать причину этого?

Ну, мы только что узнали, что поскольку фаза render не производит побочных эффектов, таких как обновление DOM, React может обрабатывать обновления компонентов асинхронно (потенциально даже делая это в несколько потоков).Однако жизненные циклы, помеченные UNSAFE, часто понимались неправильно и часто использовались не по назначению. Разработчики склонны помещать код с побочными эффектами внутрь этих методов, что может вызвать проблемы с новым подходом к асинхронному рендерингу. Хотя будут удалены только их аналоги без префикса UNSAFE, они все еще могут вызвать проблемы в предстоящем Concurrent Mode (от которого вы можете отказаться).

Вот список методов жизненного цикла, выполняемых во время второй фазы commit:

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

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

Render фаза

Алгоритм согласования (reconciliation) всегда начинается с самого верхнего fiber-узла HostRoot с помощью функции renderRoot. Например, если вы вызовете setState глубоко в дереве компонентов, React начнет с вершины, но быстро пропустит родительские узлы, пока не доберется до компонента, у которого был вызван метод setState.

Основные этапы рабочего цикла

Все fiber-узлы обрабатываются в рабочем цикле (work loop). Вот реализация синхронной части цикла:

function workLoop(isYieldy) {
  if (!isYieldy) {
    while (nextUnitOfWork !== null) {
      nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
    }
  } else {...}
}

В приведенном выше коде переменная nextUnitOfWork хранит ссылку на fiber-узел из дерева workInProgress, в котором еще есть незавершенная работа. Когда React обходит fiber-дерево, он использует эту переменную, чтобы узнать, есть ли еще какой-нибудь fiber-узел с незавершенной работой. После обработки текущего fiber переменная будет содержать либо ссылку на следующий fiber-узел в дереве, либо null. В этом случае React выходит из рабочего цикла и готов закоммитить изменения.

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

Чтобы продемонстрировать, как они используются, посмотрите на следующую анимацию обхода fiber-дерева. Для демонстрации я использовал упрощенную реализацию этих функций. Каждая функция берет для обработки fiber-узел, и по мере того, как React спускается по дереву, вы можете видеть, как меняется текущий активный fiber-узел. На анимации хорошо видно, как алгоритм переходит от одной ветви к другой. Сначала он завершает работу для дочерних узлов, а затем переходит к родительским.

Обратите внимание, что прямые вертикальные связи обозначают сиблингов (братьев и сестер), а изогнутые — детей, например, у b1 нет детей, а у b2 есть один ребенок c1.

Вот ссылка на видео, где можно приостановить воспроизведение и просмотреть текущий узел и состояние функций. Концептуально, вы можете думать о «begin» как о «шаге в» компонент, а о «complete» как о «шаге из» него. Вы также можете поиграть с примером и реализацией здесь, пока же я объясню, что делают эти функции.

Давайте начнем с первых двух функций performUnitOfWork и beginWork:

function performUnitOfWork(workInProgress) {
    let next = beginWork(workInProgress);
    if (next === null) {
        next = completeUnitOfWork(workInProgress);
    }
    return next;
}

function beginWork(workInProgress) {
  console.log('work performed for ' + workInProgress.name);
  return workInProgress.child;
}

Функция performUnitOfWork получает fiber-узел из дерева workInProgress и начинает работу, вызывая функцию beginWork. Это функция, которая запускает все действия, которые должны быть выполнены для fiber-а. Для целей данной демонстрации мы просто записываем в лог имя fiber-а, чтобы обозначить, что работа была выполнена. Функция beginWork всегда возвращает указатель на следующего ребенка для обработки в цикле или null.

Если есть следующий ребенок, он будет присвоен переменной nextUnitOfWork в функции workLoop. Однако если дочернего элемента нет, React знает, что достиг конца ветви, и поэтому может завершить текущий узел. После того, как узел будет завершен, нужно будет выполнить работу для сиблингов и вернуться к родителю после этого. Это делается в функции completeUnitOfWork:

function completeUnitOfWork(workInProgress) {
    while (true) {
        let returnFiber = workInProgress.return;
        let siblingFiber = workInProgress.sibling;
        nextUnitOfWork = completeWork(workInProgress);

        if (siblingFiber !== null) {
            // Если существует сиблинг, возвращаем его для выполнения работы для него
            return siblingFiber;
        } else if (returnFiber !== null) {
            // Если больше нет работы в этом returnFiber,
            // продолжаем цикл для завершения родителя
            workInProgress = returnFiber;
            continue;
        } else {
            // мы достигли корня
            return null;
        }
    }
}

function completeWork(workInProgress) {
  console.log('work completed for ' + workInProgress.name);
  return null;
}

Вы можете видеть, что весь код функции заключается в большом цикле while. React попадает в эту функцию, когда у узла workInProgress нет дочерних элементов. После завершения работы для текущего fiber-а, он проверяет, есть ли у него дочерний узел. Если он найден, React выходит из функции и возвращает указатель на сиблинга. Он будет присвоен переменной nextUnitOfWork, и React выполнит работу для ветви, начинающейся с этого сиблинга. Важно понимать, что на данный момент React выполнил работу только для предшествующих сиблингов. Он не выполнил работу для родительского узла. Только когда все ветви, начинающиеся с дочерних узлов, завершены, он завершает работу для родительского узла и возвращается назад..

Как видно из реализации, обе функции и completeUnitOfWork используются в основном для целей итерации, в то время как основная деятельность происходит в функциях beginWork и completeWork. В следующих статьях цикла мы узнаем, что происходит для компонента ClickCounter и узла span, когда React переходит к функциям beginWork и completeWork.

Commit фаза

Фаза начинается с функции completeRoot. Именно здесь React обновляет DOM и вызывает методы жизненного цикла до и после мутации.

Когда React доходит до этой фазы, у него есть 2 дерева и список эффектов. Первое дерево представляет состояние, которое в настоящее время отображается на экране. Затем есть альтернативное дерево, построенное во время фазы render. Оно называется finishedWork или workInProgress в источниках и представляет состояние, которое должно быть отражено на экране. Это альтернативное дерево связано с текущим деревом через указатели child и sibling.

И затем, есть список эффектов — подмножество узлов из дерева finishedWork, связанное через указатель nextEffect. Помните, что список эффектов — это результат выполнения фазы render. Весь смысл рендеринга в том, чтобы определить, какие узлы должны быть вставлены, обновлены или удалены, и какие компоненты должны вызвать свои методы жизненного цикла. И именно об этом нам говорит список эффектов. И это именно тот набор узлов, который итерируется во время фазы commit.

В целях отладки доступ к текущему дереву можно получить через свойство current fiber-корня. Доступ к дереву finishedWork можно получить через свойство alternate узла HostFiber в текущем дереве.

Основной функцией, выполняемой на этапе commit, является commitRoot. В основном, она делает следующее:

  • Вызывает метод жизненного цикла getSnapshotBeforeUpdate на узлах, помеченных эффектом Snapshot.

  • Вызывает метод componentWillUnmount жизненного цикла для узлов, помеченных эффектом Deletion.

  • Выполняет все вставки, обновления и удаления в DOM

  • Устанавливает дерево finishedWork в качестве текущего.

  • Вызывает метод жизненного цикла componentDidMount на узлах, помеченных эффектом Placement.

  • Вызывает метод componentDidUpdate жизненного цикла для узлов, помеченных эффектом Update.

После вызова метода предварительной мутации getSnapshotBeforeUpdate, React фиксирует все побочные эффекты внутри дерева. Он делает это в два прохода. Первый проход выполняет все вставки, обновления, удаления и размонтирования DOM (хоста). Затем React назначает дерево finishedWork на FiberRoot, помечая дерево workInProgress как current. Это делается после первого прохода фазы commit, чтобы предыдущее дерево было актуальным во время componentWillUnmount, но до второго прохода, чтобы законченная работа была актуальной во время componentDidMount/Update. Во время второго прохода React вызывает все остальные методы жизненного цикла и обратные вызовы. Эти методы выполняются как отдельный проход, так что все размещения, обновления и удаления во всем дереве уже были вызваны.

Дополнительно:  Синий Экран Смерти | Windows вики | Fandom

Вот сниппет функции, которая выполняет описанные выше шаги:

function commitRoot(root, finishedWork) {
    commitBeforeMutationLifecycles()
    commitAllHostEffects();
    root.current = finishedWork;
    commitAllLifeCycles();
}

Каждая из этих подфункций реализует цикл, который итерирует список эффектов и проверяет их тип. Когда он находит эффект, соответствующий цели функции, он применяет его.

Pre-mutation методы жизненного цикла

Вот, например, код, который выполняет итерацию по дереву эффектов и проверяет, имеет ли узел эффект Snapshot:

function commitBeforeMutationLifecycles() {
    while (nextEffect !== null) {
        const effectTag = nextEffect.effectTag;
        if (effectTag & Snapshot) {
            const current = nextEffect.alternate;
            commitBeforeMutationLifeCycles(current, nextEffect);
        }
        nextEffect = nextEffect.nextEffect;
    }
}

Для классового компонента это действие означает вызов метода жизненного цикла getSnapshotBeforeUpdate.

Обновления DOM

commitAllHostEffects — это функция, с помощью которой React выполняет обновление DOM. Функция в основном определяет тип операции, которую необходимо выполнить для узла, и выполняет ее:

function commitAllHostEffects() {
    switch (primaryEffectTag) {
        case Placement: {
            commitPlacement(nextEffect);
            ...
        }
        case PlacementAndUpdate: {
            commitPlacement(nextEffect);
            commitWork(current, nextEffect);
            ...
        }
        case Update: {
            commitWork(current, nextEffect);
            ...
        }
        case Deletion: {
            commitDeletion(nextEffect);
            ...
        }
    }
}

Интересно, что React вызывает метод componentWillUnmount как часть процесса удаления в функции commitDeletion.

Post-mutation методы жизненного цикла

commitAllLifecycles — это функция, в которой React вызывает все оставшиеся методы жизненного цикла componentDidUpdate и componentDidMount.


Наконец-то мы закончили. Дайте мне знать, что вы думаете о статье или задайте вопросы в комментариях. Посмотрите следующую статью из цикла Глубокое объяснение обновления состояния и пропсов в React. У меня в работе еще много статей, в которых подробно рассказывается о планировщике, процессе согласования детей и о том, как строится список эффектов. Я также планирую создать видео, в котором покажу, как отлаживать приложение, используя эту статью в качестве основы.

Следующая статья серии (ссылка на перевод) — Fiber изнутри: Обновления состояния и пропсов в React


На основании Вашего запроса эти примеры могут содержать грубую лексику.


На основании Вашего запроса эти примеры могут содержать разговорную лексику.


Plants produce very little fibrous root and should be planted in their final positions when still small.



Растения дают очень мало волокнистых корней и должны быть посажены, когда они еще маленькие.


However, the coconut tree has a fibrous root system.


This plant with a fibrous root system, spread very fast, as they propagate vegetatively and through seeds.



Это растение с волокнистой корневой системой, распространяется очень быстро, так как они размножаются вегетативно и с помощью семян.


Its fibrous root system and prolific seeding habit have led to its use in erosion control in some parts of the world.



Его волокнистых корневой системы и плодовитый привычка посева привели к его использования в борьбе с эрозией в некоторых частях мира.


The dense and fibrous root system prevents the growth of neighbouring plants.



Густая корневая система препятствует росту соседних растений.


An asparagus planting is usually not harvested for the first 3 years after the crowns are planted allowing the crown to develop a strong fibrous root system.



Обычно спаржу не собирают в течение первых трех лет после посадки коронок, что позволяет короне вырабатывать сильную волокнистую корневую систему.


Oats, barley, wheat, and rye are all cereal grasses that produce a dense, fibrous root mass and a great deal of carbon-heavy biomass above ground.



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


The wheat plant has a fibrous root system, the stem is hollow, or filled with parenchyma, is a straw divided along the entire length by septa, which are stem nodes, and the distances between them are internodes, all of them in wheat 5-7.



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


It is naturally a wetland tree, and develops a shallow, fibrous root system, unlike many oaks, which have a strong, deep taproot when young.



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

Ничего не найдено для этого значения.

Результатов: . Точных совпадений: . Затраченное время: мс


Documents


Корпоративные решения


Спряжение


Синонимы


Корректор


Справка и о нас

Индекс слова: 1-300, 301-600, 601-900

Индекс выражения: 1-400, 401-800, 801-1200

Индекс фразы: 1-400, 401-800, 801-1200

Fibrous root taproot

  • reticulate fibrous structure — волокнисто-сетчатая структура
  • fibrous filter — волокнистый фильтр
  • fibrous capsule — фиброзная капсула
  • fibrous microstructure — волокнистая микроструктура
  • release of fibrous bands — иссечение фиброзных тяжей
  • rough fibrous — грубая фиброзная
  • fibrous scar tissue — Волокнистая рубцовая ткань
  • fibrous scar — фиброзный рубец
  • fibrous bands — волокнистые полосы
  • fibrous products — волокнистые продукты
  • fibrous peat — волокна торфа
  • fibrous iron ore — железная руда с волокнистой текстурой
  • fibrous insulation-coated refractory metal — тугоплавкий металл с волокнистым ТЗП
  • fibrous ring — фиброзное кольцо
  • fibrous network — волокнистая сеть
  • Синонимы & Антонимы

    «MORPHOLOGY OF VEGETATIVE ORGANS»— Presentation transcript

    MORPHOLOGY OF VEGETATIVE ORGANS
    Assistant professor Ludmila Anatolyevna Liubakouskaya Botany and Ecology Chair

    Introduction to pharmaceutical botany
    Pharmaceutical botany is the discipline forming theoretical knowledge of flora and practical skills of plants analysis necessary in future work of the specialist pharmacist. Botany as a science, studies an external and internal structure of plants, characteristics of processes of vital activities, classification, interrelation with environmental conditions, distribution, significance in nature and human life. Complex studies of plants caused need to separate from botany fundamental disciplines important for pharmacy

    Meaning of Botany for Pharmacy:
    Anatomy of plants – basis of microscopical analysis of medicinal plant raw material. Morphology – basis of macroscopical analisys of medicinal plant raw material. Physiology of plants is necessary for studying the metabolism and the accumulation of biologically active substances. Systematic of plants is necessary for identification plants in nature. Botanical Geographic – is basis of rational storing medicinal herbs. Ecology of plants – on introduction plants into the culture.

    Basic plant parts

    Vegetative organs of plants are the organs performing main functions of nutrition and metabolism with the environment. Vegetative organs include: the leafy-stem spears providing photosynthesis; roots providing water supply and mineral nutrition.

     Structure of the root The main root and side roots are distinguished in a root. The primary root is formed in a germ, it is focused down and becomes the main root in gymnospermous and floral plants. Side roots are formed on the main root.

    Types of Roots (based on position and origin)Primary or seed root — the first root to grow from the radicle of embryo; tip of main root axis.    Secondary — any root sprouting from the pericycle within the primary root; lateral roots.    Adventitious — Arising from organ other than root, such as the lower portion of the stem; usually lateral. Пошин нижняя часть

    The types of root systems
    Tap root system —  It is the root system that develops from the radicle and continues as the primary root (tap root) which gives off lateral roots. Fibrous root system —  In this root system, the primary root is short lived. A cluster of slender, fiber-like roots arises from the base of the radicle and plumule which constitute the fibrous root system. Fibrous root system is the main root system of monocots, e.g. maize, grasses, wheat. Мочковатая корневая система — В этом корневой системы, основной корень недолгим. Кластер тонкими, похожих на волокно корней возникает от основания корешка и перышка которые составляют волокнистый корневую систему Plumule плюмьюл волокно

    Тьюберез туберез корнеклубни

    Modifications of roots

    Macroscopic diagnostic features:
    Roots (Radices), rhizomes (Rhizomata), tubers (Tubera), bulbs (Bulbi), corms(Bulbotubera) are dried out or fresh underground organs of perennial plants, which are clean from the soil and free from traces of stems and leaves. Size and form The features of surface and fissure(fracture) The color of surface on a fresh fissure(fracture) Smell and taste

    А shoot — stem of a plant with leaves
    A stalk, an axis of higher plants, making a spear together with the leaves, serves for transport of water and organic substances between roots and leaves The main function of the stalk is transport of mineral substances dissolved in water from the root to leaves, buds, flowers (the ascending flow) and organic substances – photosynthesis products to the root (the descending flow). Besides the main function, the spear also performs other functions: a) Supporting function – it provides a plant position in the environment; b) Assimilating function – young spears participate in photosynthesis; c) Accumulating function– in a stalk nutrients are accumulated in reserve. Эсендинг восходящий флоу ток Стебель, осевой орган высших растений, вместе с листьями составляющий побег, служит для передвижения воды и органических веществ между корнями и листьями. Главная функция стебля – транспорт растворенных в воде минеральных веществ от корня к листьям, почкам, цветкам (восходящий ток) и органических веществ – продуктов фотосинтеза к корню (нисходящий ток). Кроме главной функции, побег выполняет и другие функции: а) Опорная – обеспечивает расположение растения в пространстве; б) Ассимилирующую – молодые побеги участвуют в фотосинтезе; в) Запасающую – в стебле откладываются в запас питательные вещества;

    Structure of the stalk The parts of a plant. Note stem, leaf, and petiole. Leaves are attached to stems and branches. Листья крепятся к стеблей и ветвей.

    Structure of the stalk parts of a stalk from which side organs branch (branches, leaves and etc.) are called nodes, the parts between the nodes are called internodes. Stalks have metameric structure Growth of a stalk in length is carried out owing to: — activity of the top meristem of the spear, (cone of increase.) — intercalary (inserted) (for example, in cereals). асти стебля, из которого побочные органы филиал (филиалы, листья и т.д.) называются узлы, детали между узлами называют междоузлиями которые. Стебли у метамерными структуру Рост стебля в длину осуществляется за счет: — (. Конуса роста) деятельность в верхнем меристемы копья, — Вставочные (установлена) (например, в зерновы

    Дополнительно:  Не регулируется яркость экрана на ноутбуке, что делать? Как настроить яркость

    The location of a stem in a space:
    1 — upright, 2 — clinging, 3 — twisting, 4 — climbing with suckers, 5 — creeping, 6 — trailing

    The type of ramification:
    1-2 — tip branching, forked increase(equal- and anisoforked); 3-5 — lateral branching, monopodial increase with alternative (3), opposite (4) and whorled (5) location of lateral axes; 6-8 — lateral branching, monochasial (6), dichasial or falseforked(7), pleiochasial(8) increase; 9 — tillering;10 — columnar stem

    The form of cross-section:
    1 — cylindrical; 2 — elliptical; 3 – rounded tetrahedral; 4 – concave tetrahedral; 5 — trihedral; 6 — polyhedral; 7 — articulate; 8 — grooved Раундид тетра.хидрэл

    Вотеспауд эрайзез Тетндрилз твайнинг секьюа клайминг ветикал сефейсис

    Types of modified stems

    Types of modified stems

    Macroscopic diagnostic features of stems:
    -The location of a stem in a space -The type of ramification -The form of cross-section -Sizes (length and diameter at a base) -The features of surface, pubescence.

    Leaves (function, structure)
    Сто ьюринг джеминейшен

    Different types of leaves The dicotyledonous leaf
    A typical leaf of a dicotyledonous plant consists of  two main parts :  •    the blade •    the petiole  The blade includes an apex, a margin, a vein and a base. Dicotyledonous дайкоти.лидененс

    Structure of a leaf Simple leaves have a single blade.
    tip — the terminal point of the leaf. blade — the flattened, green, expanded portion of a leaf. margin — edge of a leaf. midrib — the most prominent central vein in a leaf. lateral veins — secondary veins in a leaf. petiole — the leaf stalk (connects blade to stem). stipules — leaf-like appendages (at the base of the petiole of some leaves). They may protect the young leaf and may be modified into spines or tendrils. tip типверхушкаApex of the leaf blade, at the opposite end from the part attached to the petiole; this part can vary markedly in shape. Вершина пластинки листа, в противоположном конце от части была свойственна черешку; эта часть может измениться заметно по форме. the flattened флетенд уплощенный portion поушн часть Midrib мидриб главная жилкаПолое проектирование, которое расширяет черешок в лезвие и несет сок; это формирует основание скелета листа. Central сентрел центральный главный Lateral летрл боковой Appendages эп.ендеджес придаток  spines спайнз шипы колючки Sheath шиз влагалище листа Distension of the petiole, partly or completely surrounding the stem Растяжение черешка, частично или абсолютно окружающий основа leaf axil эксел влагалищеPoint at which the petiole attaches to the stem nodeПункт, в котором черешок свойственен узлу основы Совет — конечная точка листа. Лезвие — уплощенный, зеленый, расширенная часть листа. Маржа — край листа. жилка — самый выдающийся центральной вены в листе. боковые жилки — вторичные жилки в листе. черешок — лист стебель (соединяет лезвие, чтобы остановить). прилистники — листовидные придатки (у основания черешка листьев некоторых). Они могут защитить молодую лист и могут быть изменены в колючки или усиками

    Types of leaves on an attachment to a stalk

    Leaflet Arrangement on Petiole
    Simple – Leaf blade is one continuous unit (cherry, maple, and elm) Compound – Several leaflets arise from the same petiole Pinnately compound – Leaflets arranged on both sides of a common rachis (leaf stalk), like a feather (mountain ash) Palmately compound – Leaflets radiate from one central point (Ohio buckeye and horse chestnut) Double pinnately compound – Double set of compound leaflets Листовка договоренность о черешка Простой — Листовая пластинка является одной непрерывной блок (вишня, клен, вяз и) Соединение — Несколько листовки возникают из того же черешок ? Перисто соединение — Листовки расположены на обеих сторонах общих рахиса (лист стебля), как перо (рябины) Пальчато сложные — Листовки излучать из одной центральной точки (штат Огайо Бакай и конского каштана) Двухместный перисто соединение — двойной набор составных листовок

    Forms of a blade The form of a blade is determined by proportion of the length to the width in the widest part of the blade. For example: lanceolate, ovate, peltate, linear, reniform, orbiculate cordate, hastate, spatulate Препоушен, ленгз,видз, вайдест Лансиэлейт  — narrow blade that is longer than it is wide, ending in a point., овейт — egg-shaped blade., peltate щитовидныйpetiole attached perpendicularly to the center of the blade’s underside, linear –линие линейный лong and very narrow blade and almost parallel margins. , reniform –почковидный, Orbi.кьюлейтculate –округлый somewhat rounded blade, . cordate –кодейт-серцевидныйheart-shaped blade, hastate хезтейт копьевидныйspear-shaped blade, spatulatespear-shaped blade

    Leaf Arrangement on Stems
    Alternate – Arranged in staggered fashion along stem (willow) Opposite – Pair of leaves arranged across from each other on stem (maple) Whorled – Arranged in a ring (catalpa) Rosette – Spiral cluster of leaves arranged at the base (or crown) (dandelion) Arrangement э.рейджмент расположение Alternate ол.тенед очередное Arranged эрейнджд расположение Staggered стегед шахматном порядке Fashion фашн виде Willow вилов ива Opposite опезит напротив Pair пеэ пара Maple мейпл клен Whorled вээлд мутовчатое Crown краун корона Dandelion дан.дельен одуванчик Альтернативный — Организованные в шахматном порядке вдоль стебля (ива) Напротив — пара листьев, расположенных напротив друг друга на стебле (клен) Мутовчатыми — располагаются в кольце (катальпа) Розетка — Вихревой кластер из листьев, расположенных у основания (или коронки) (одуванчик)

    Leaf margins Margins маджинс край Entire интае цельный
    Serrulate серулейт мелкозубчатый Serrate серейт пильчатый Dentate .дентейт зубчатый Crenate кренейт городчатый Undulate андюлейт волнистый Sinuate синьюэйт извилистый Incised инсайзд выемчатый

    Margin of the leaf (Leaf edges)
    Leaf edges vary markedly, depending on the shape and depth of their indentations Leaf edge with rounded teeth. Leaf edge indented with deep notches. Leaf edge with no indentations. Leaf edge surrounded by short thin hairs called cilia. Leaf edged with teeth of different sizes, the main tooth often having smaller teeth. Leaf edged with pointy teeth of similar size. Leaf edges край листа Leaf edges vary markedly, depending on the shape and depth of their indentations — Края листика варьируются заметно, в зависимости от формы и глубины их углублений Crenate кринейт городчатый Края листика округленными лопастямиLeaf edge with rounded teeth. Lobate леобейт разделённый на лопасти (о листе) Leaf edge indented with deep notches. Края листика заказаны с глубокими метками. Entire интае цельныйLeaf edge with no indentations. Края листика без углублений. ciliate реснитчатыйLeaf edge surrounded by short thin hairs called cili Края листика, окруженные короткими тонкими волосами, названными cili doubly dentate дабл дентейт дважды зубчатыйLeaf edged with teeth of different sizes, the main tooth often having smaller teeth. Лист продвинулся с зубами различных размеров, главным зубом, часто имеющим меньшие зубы. Dentate зубчатыйLeaf edged with pointy teeth of similar size. Лист продвинулся с заостренными зубами подобного размера.

    Margin Types crenate Leaf edge with rounded teeth. lobate
    Leaf edge indented with deep notches. Leaf edge with no indentations. Leaf edge surrounded by short thin hairs called cilia. Leaf edged with teeth of different sizes, the main tooth often having smaller teeth. Leaf edged with pointy teeth of similar size. на данном слайде указан край листа с их характеристикой on this slide the sheet edge with their characteristic is specified

    Shape of Leaf Apex and Base
    Leaf Tip Shapes.  Leaf Base Shapes. Shape шейп форма

    Leaf venation (arrangement of veins)
    pinnate venation — feather-like, net venation with lateral veins extending from a central midrib. palmate venation — finger-like, net venation with several major veins diverging from the union of the petiole and the leaf blade. parallel venation — principal veins parallel to the axis of the leaf. Dichotomous venation – Somewhat parallel vein sections, forming a ‘Y’, found in Ginkgo trees. Лист жилкованием (расположение вен) перистые жилкование — перистые, чистая жилкование с боковыми жилками, простирающихся от центральной жилки в. пальчато жилкование — палец, как чистая жилкование с несколькими крупными венами, расходящихся от союза черешка и листовой пластинки. параллельно жилкование — главные вены, параллельно оси листа.

    Simple and compound leaf
    In simple leaves, the leaf surface is not divided into leaflets. It has only one blade or lamina. The leaves of papaya, mango and money plant are simple leaves. In compound leaves, the leaf lamina is divided and is not a unit. A leaf with more than one blade is known as a compound leaf. The blades of a compound leaf are called leaflets. Rose, neem and walnut have compound leaves. Волнат грец орех Простой и сложный лист В простых листьев, листовой поверхности не делится на листовках . Она имеет только одно лезвие или пластинку . Листья папайи , манго и денег растения простые листья . В сложных листьев, листьев пластинка разделена и не в целом. Лист с более чем одним лезвием известен как сложного листа . Лопасти сложного листа называются листовки. Роза, нима и грецкого ореха составные листья.

    Compound leaves have a blade divided into individual leaflets. leaflet — secondary leaf of a compound leaf. rachis — an extension of the petiole bearing leaflets. petiolule — the leaflet stalk. petiole — the leaf stalk lateral veins — secondary veins in a leaf. stipules — leaf-like appendages (at the base of petiole of some leaves).

    Leaves are the major site for photosynthesis in most plants. The flat leaf blade is specialized for catching sunlight. Leaf characteristics vary greatly from plant to plant and are useful in classification and identification. Leaves are either Simple or Compound.

    Type compound leaves Leaves with blades divided into several distinct sections, called folioles, the arrangement of which determines the leaf type. Листовые пластинки могут разделяться на отдельные части, названные листочками, которых определяет тип листа. abruptly pinnate эбраптли пинейт парноперистый Compound feathered leaf ending in two folioles on each side of the main petiole. Состав украсил лист, заканчивающийся в двух листочках на каждой стороне главного черешка. odd pinnate непарноперистый Compound feathered leaf with a main petiole ending in a single foliole Состав украсил лист с главным черешком, заканчивающимся в единственном листочк Pinnatifid перисторассечённый Compound leaf with folioles on both sides of a common petiole. Сложный лист с листочками с обеих сторон общего черешка. Palmate пелмейтпальчатыйCompound leaf with all its folioles attached at the same point, at the apex of the petiole Сложный лист со всеми его листочками был свойственен в том же самом пункте в вершине черешка Trifoliolate трайфеулиелейт тройчатыйLeaf having three distinct folioles. Лист, имеющий три отличных листочка.

    Difference between simple leaves and compound leaves, simple and compound leaf forms
    1. Consists of a single lamina. 2. The bud is usually present at the leaf axil. 3. Stipules may be present at the base. Examples: mango, peepal, guava Consists of several leaflets. The bud is not present at the axils of the leaflets. Stipules are not present at the base of the leaflets. Examples: neem, rose, tamarind Темеринд инд. финик

    on this slide the main harateristik of leaves are presented

    Examples of plants on this slide examples of plants are presented

    Modification of leaves

    Thank you for attention!
    One moment please! For practical class you must have an album, coloured pencils, a pen, lead pencil, a rubber, an exersise – book. Guidelines in botany will be presented on the information stend of the botany chair on the third floor. Калед лед Is everythink clear .эврисинк клеа

    Оцените статью
    Master Hi-technology
    Добавить комментарий