Часть 3. Строитель: рендерер и Block Tree
Когда реактивность дала сигнал, а компилятор подготовил план, вступает рендерер. Его задача - обновить реальный дом с минимальными затратами.
🧩 И снова ресторан: В ролях: повар (Vue рендерер), клиент (пользователь приложения), заказ (VDOM), блюда (DOM). Клиент делает заказ из 10 блюд (уважает кулинарию). Повар все приготовил и собирается отдать блюда, а тут обновляется заказ - "клиент попросил сделать блюдо #1 острее". Умный повар не станет готовить с нуля все 10 блюд, он просто кинет перца любителю пикантности в одно блюдо. Звучит как база, но если бы не рендерер Vue (и прочие штуки из серии постов), то наш необразованный повар пошел бы готовить все с нуля дабы добавить остринки в одно блюдо.
⚙️ Под капотом: В отличие от классического VDOM, где нужно рекурсивно обходить все дерево, Vue 3 использует концепцию Block Tree - компонент разбивается на блоки (динамические и статичные). Внутри блока динамические узлы собраны в плоский массив (благодаря patchFlags из прошлого поста). При обновлении Vue пропускает статичные поддеревья целиком. Он берет плоский массив динамических узлов и применяет к ним точечные патчи.
❓ Зачем это нужно: Все найденные отличия синхронно применяются к DOM в рамках вычищения очереди микротасок. После этого JS отдает управление браузеру, и тот делает перерисовку. Это избавляет от лишних перерисовок компонента. А чтобы избежать layout shift на стороне браузера, рендереру нужно помочь (читай совет).
💡 Совет: Рендерер Vue отлично точечно обновляет DOM, но он не может отменить физику браузера. Избегайте частых изменений реактивных данных, которые вызывают layout shift (например, частое изменение width или top через JS). Если нужно что-то двигать — используйте CSS transform, чтобы рендерер Vue и браузер работали в синергии, а не мешали друг другу