Skip to content

Представление VNode с помощью битов

Представление типов VNode с помощью битов

Существуют различные типы VNode. Например, на данный момент реализованы следующие:

  • узел компонента
  • узел элемента
  • текстовый узел
  • является ли дочерний элемент текстом или нет
  • является ли дочерний элемент массивом или нет

И в будущем будут реализованы еще больше типов VNode. Например, slot, keep-alive, suspense, teleport и т.д.

В настоящее время ветвление выполняется с помощью условий типа type === Text, typeof type === "string", typeof type === "object" и т.д.

Проверка этих условий по одному неэффективна, поэтому давайте попробуем представить их с помощью битов, следуя реализации оригинала. В Vue эти биты называются "ShapeFlags". Как следует из названия, они представляют форму VNode. (Строго говоря, в Vue для определения типа VNode используются ShapeFlags и символы, такие как Text и Fragment.) https://github.com/vuejs/core/blob/main/packages/shared/src/shapeFlags.ts

Битовые флаги относятся к обработке каждого бита числа как определенного флага.

Рассмотрим следующий VNode в качестве примера:

ts
const vnode = {
  type: 'div',
  children: [
    { type: 'p', children: ['hello'] },
    { type: 'p', children: ['hello'] },
  ],
}

Сначала начальное значение флага равно 0. (Для простоты это объяснение дается с использованием 8 битов.)

ts
let shape = 0b0000_0000

Теперь этот VNode является элементом и имеет массив дочерних элементов, поэтому устанавливаются флаги ELEMENT и ARRAY_CHILDREN.

ts
shape = shape | ShapeFlags.ELEMENT | ELEMENT.ARRAY_CHILDREN // 0x00010001

С помощью этого мы можем представить информацию о том, что этот VNode является элементом и имеет массив дочерних элементов, используя всего одно число, называемое "shape". Мы можем эффективно управлять типами VNode, используя это в ветвлении в рендерере или других частях кода.

ts
if (vnode.shape & ShapeFlags.ELEMENT) {
  // Обработка, когда vnode является элементом
}

Поскольку мы не реализуем все ShapeFlags в этот раз, попробуйте реализовать следующее в качестве упражнения:

ts
export const enum ShapeFlags {
  ELEMENT = 1,
  COMPONENT = 1 << 2,
  TEXT_CHILDREN = 1 << 3,
  ARRAY_CHILDREN = 1 << 4,
}

Вот что нужно сделать:

  • Определить флаги в shared/shapeFlags.ts
  • Определить shape в runtime-core/vnode.ts
    ts
    export interface VNode<HostNode = any> {
      shapeFlag: number
    }
    Добавить это и вычислить флаг в функциях типа createVNode.
  • Реализовать логику ветвления на основе shape в рендерере.

На этом объяснение этой главы закончено. Давайте начнем реализацию!

Released under the MIT License.