/ Vue Js

Что нужно знать о Vue3 в 2020 году

VueJS является одним из самых популярных фреймворков для фронтенд разработки на данный момент. Это популярный фреймворк, популярность которого продолжает расти всё больше, о чём говорит график еженедельных скачивания в 2019 году.
stats1

И релиз Vue3 в начале 2020 года должен только увеличить его популярность.

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

Vue3 также предоставляет разработчикам больше контроля (если это требуется). Vue3 даёт нам возможность более точно контролировать то, что происходит в наших проектах, начиная с написания собственных методов компиляции и рендеринга и заканчивая возможностью прямой работой с API реактивности во Vue.

Ниже приведены некоторые из самых значительных изменений, которые планируется внести, насколько можно верить словам основателя фреймворка, а также из RFC (запросы пользователей) репозитория Github.

Vue3 работает на основе Proxy-наблюдателей.
Реактивность лежит в основе фреймворка VueJS. Чтобы данные корректно отображались в представлении сразу же при их изменении, необходимо, чтобы кто-то, наблюдали за ними, следил за изменениями и обновлял все зависимые части.

Vue2 использует Object.definePropert для создания геттеров и сеттеров для реализации реактивности.

Но при этом подходе существует две основные проблемы - и, на самом деле, они настолько распространены, что даже упоминаются в официальной документации.

  1. Реактивные свойства не могут быть динамически добавлены/удалены.
  2. Существует 2 проблемы, связанные с динамическими массивами.
    • Изменение элемента путем обращения к нему по индексу не является реактивным.
    • Изменение длины массива не является реактивным.
// Установка элемента при обращении к нему по индексу - НЕ РЕАКТИВНО
vm.items[indexOfItem] = newValue
// Изменение длины массива  - НЕ РЕАКТИВНО
vm.items.length = newLength


В чём польза использования Proxy наблюдателей за изнением данных?

Решение Vue3 заключает в себе использование прокси-наблюдателей для снятия функциональных ограничений с системы реактивности.

Ключевое различие между старой и новой системами заключается в том, что в Vue2, Object.defineProperty изменяет исходные данные, в то время как Proxies нет. Вместо этого он виртуализирует целевые данные и устанавливает различные обработчики, которые перехватывают данные через геттеры и сеттеры и изменяют не оригинальные данные, а созданную на их основе копию.

Применение новой системы значит, что реактивные свойства могут быть добавлены/удалены без использования vm.$set. Это также исправляет вопросы реактивности Vue2 при работе с массивами.

Как лучше всего подытожить автор Vue, благодаря архитектуре, основанной на Proxy, добились следующего:

  • Обнаружение добавления/удаления свойств
  • Обнаружение случаев изменения индекса массива/длины
  • Поддержка для Map, Set, WeakMap и WeakSet

В VueMastery приведена отличная демонстрация того, как добиться улучшений, с помощью Proxy.

Введение в Composition API

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

На данный момент, если вы работали в Vue, вы использовали то, что называется Options API. Options API организует код по свойствам: data, computed, methods и так далее.

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

Поддержка и читабельность кода стали основными проблемами.
Давайте посмотрим, как работает Composition API.

import { reactive, computed } from 'vue'
export default {
   setup() {
		// API Vue composition описывает реактивные свойства ядра
		let state = reactive({
			input: "",
			groceries: [],
			groceriesLeft: computed(() => groceries.length)
		});
		function addGrocery() {
			state.groceries.push(state.input);
			state.input = "";
		}
		function deleteGrocery(index) {
			state.groceries.splice(index, 1);
		}
		return { 
			state, 
			addGrocery, 
			deleteGrocery 
		};
   }
}

Пойдем по порядку и разберемся с тем, что здесь происходит.

API Vue Composition описывает множество основных функциональных возможностей Vue, таких, как реактивность и компонентные методы. Поэтому мы должны импортировать их.

import { reactive, computed } from 'vue'

Применение метода setup() является одним из самых больших изменений в Vue3. По сути, он позволяет определить, какие данные/функции передаются из компонента обратно в шаблон. Всё, что он возвращает - доступно в шаблоне.

export default {
   setup() {
   // ...

Мы можем задавать реактивные данные, хуки жизненного цикла, вычисляемые свойства, определённые методы и возвращать всё, что захотим.

let state = reactive({
	input: "",
	groceries: [],
	groceriesLeft: computed(() => groceries.length)
});

Оборачивая все эти данные методом reactive, все эти данные автоматически становятся реактивными. Этот шаблон состояния взят из документации по Composition API.

Следует отметить, что мы объявляем переменную groceriesLeft. Как видите, она является computed-свойством и определяется прямо в методе setup(). Больше нет никаких отдельных вычисляемых свойств, теперь в одном месте определяются и data и computed свойства!

function addGrocery() {
	state.groceries.push(state.input);
	state.input = "";
}
function deleteGrocery(index) {
	state.groceries.splice(index, 1);
}

Это просто определение типичных старых функций. Единственное, что тут действительно уникально, это то, что поскольку все реактивные данные хранятся в объекте состояния, мы должны сохранить его в переменную и обращаться к его своствам. Но это не специфично для Vue3 - это просто обычные объекты на Javascript.

return { 
	state, 
	addGrocery, 
	deleteGrocery 
};

Наконец, мы возвращаем эти данные из метода setup(). Что делает эти данные и методы доступными внутри шаблона. К счастью, код шаблона все так же сохраняет прежний формат описания.

Когда это было впервые представлено, в сообществе Vue были тонны возмущений по этому поводу, потому что люди не хотели вынужденно переделывать и переосмысливать всю свою логику компонентов. Однако, впоследствии было решено, добавить эти изменения в качестве опциональных, и люди все ещё могут использовать Options API без каких-либо препятствий.

Если вы уже хотите начать практиковаться, вы можете использовать API Vue Composition в своих проектах.

Теперь вы можете использовать Suspense в Vue

Suspense - это функция React, которую добавили и в Vue3. Она позволяет вашему компоненту отображать временное содержимое (заглушку) до тех пор, пока ваш основной контент страницы не будет готов к отображению. Например, как часто бывает, что мы открываем страницу, и видим прелоадер, который пропадает только когда вся бизнес-логика на странице отработает.

Это полезно, когда вы хотите асинхронно загрузить содержимое в вашем методе setup(). Смотря на код репозитория Vue-Next, кажется, что setup() - это асинхронный метод, который возвращает Promise. Этот Promise отлавливается компонентом Suspense, который выводит контент-заглушку до тех пор, пока основной код не будет полностью загружен и обработан.

Suspense будет полезен для:

  • Создания страниц с загрузкой
  • Ожидания ответов от API для обработки
  • Подходит для любого вида получения данных по API или асинхронной загрузки

При этом, это очень легко внедряется. Всё, что вам нужно будет сделать, это обернуть ваш код в Suspense компонент и определить ваше основное содержимое и содержимое заглушки.

<Suspense>
  <template >
    <Suspended-component />
  </template>
  <template #fallback>
    Контент заглушка (Fallback Content)
  </template>
</Suspense>

Фрагменты в Vue3

Фрагменты - бескорневые компоненты, т.е. компоненты, которые в template содержат больше одного родительского элемента. В Vue2 каждый компонент должен иметь один и только один корневой элемент.
И иногда это может быть той ещё головной болью.

Есть несколько случаев, когда возврат нескольких дочерних элементов гораздо упростил бы задачу. Например, давайте возьмем пример из React и скажем, что у вас есть структура таблицы с пользовательским компонентом под названием Columns.

<table>
    <tr>
      <Columns />
    </tr>
 </table>

Наш компонент, по задумке, должен возвращать несколько элементов <td>. Но в настоящее время компоненты Vue должны иметь один корневой элемент.

Шаблон компонента Columns может быть похож на этот, что вызовет некоторые проблемы с разметкой.

<div>
    <td>Hello</td>
    <td>World</td>
</div>

Вот здесь Фрагменты как раз очень к стати. Они позволяют возвращать несколько элементов, не ломая при этом разметку, что делает такие задачи супер простыми.

Шаблон компонента с использованием Fragment в Vue3 может выглядеть так.

<Fragment>
    <td>Hello</td>
    <td>World</td>
</Fragment>

И теперь, поскольку это вернет два элемента <td>, таблица будет валидной, и это будет итоговый, желанный результат.

<table>
    <tr>
        <td>Hello</td>
        <td>World</td>
    </tr>
 </table>

Это именно то, что нам и было нужно. В настоящее время существует неофициальная библиотека Vue Fragment, которая использует внутренние директивы для того, чтобы получить все дочерние элементы компонента и переместить их в нужное место.

Ох. А ещё Portals

Portals - это еще одна функция, изначально появившаяся в React, которая в настоящее время планируется к внедрению в Vue3.

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

Это очень полезно, когда вы хотите отправить данные во всплывающее окно, боковую панель или что-то подобное.

Как и в случае с Fragments, в настоящее время существует неофициальная библиотека portal-vue, которая переносит эту функциональность на Vue2. В соответствии с репозиторием vue-next, Portals будет включен в Vue3.

Вот скриншот примера и код из документации portal-vue.
portal

<template>
  <div>
    <div>
      <p>
        The content below this paragraph is
        rendered in the right/bottom (red) container by PortalVue
      </p>
      <Portal to="right-basic">
        <p class="red">
          This is content from the left/top container (green).
          The cool part is, it works across components,
          so you can send your content anywhere!
        </p>
      </Portal>
    </div>
    <PortalTarget name="right-basic"></PortalTarget>
  </div>
</template>

В Vue3 проведена оптимизация рендеринга

Огромная часть Vue3 стала значительно быстрее и эффективнее. На самом деле, по информации из дискуссий создателя Vue.Js, внутренние тесты показали, что стили шаблонов в Vue3 стали компилироваться на ~120% быстрее, чем в Vue2.

Были проведены две ключевые оптимизации, которые помогли улучшить скорость рендеринга Vue3:

  1. Оптимизации блочного дерева
  2. Статический подъем деревьев

Давайте рассмотрим подробности о каждом из них.

Оптимизации блок-дерева

Использование виртуального DOM имеет естественное узкое место, потому что каждый компонент должен отслеживать свои зависимости.

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

Одна вещь, которую заметила команда Vue, заключается в том, что в компонентах большая часть структуры узла является статической. И если секция на самом деле была динамической (из-за директивы v-if или v-for), то большое количество содержимого внутри неё всё равно было статическим.
dynamic

Используя эту идею, Vue3 разбивает шаблон на статические и динамические секции. Теперь, когда рендер-функция знает, какие узлы являются динамическими, он не тратит время на проверку статических узлов на наличие изменений.

Это значительно сокращает количество элементов, за которыми нужно следить в реактивном режиме.

Объединение всех этих узлов создаёт дерево блоков или шаблон, разделенный на блоки узлов на основе директив (v-if, v-for).

В дереве блоков каждый узел содержит:

  • Полностью статическую структуру узлов
  • Статический контент, который не нужно отслеживать.
  • Динамические узлы, которые могут храниться в обычном массиве
    three_block1

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

Статический подъем деревьев

В то время как статический подъём деревьев не является чем-то новым (он существует в Vue 2.0), в Vue3 добавили гораздо более агрессивные методы для повышения скорости проекта. Как следует из названия, статический подъем деревьев не пересканирует статические элементы, которые не имеют никаких зависимостей. Вместо этого, он использует один и тот же элемент.

Это значительно сокращает работу виртуального DOM-а и экономит много накладных расходов проекта, в первую очередь на сборке мусора.

В Vue3 статический подъем является гораздо более агрессивным, для того, чтобы работать как можно эффективнее.

Поддержка Typescript

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

Поэтому команда Vue предоставила выбор: если вам нужен Typescript, используйте его; если нет, придерживайтесь стандартного синтаксиса Javascript. Оба варианта работают просто отлично.
typescript

Если ты такой же, как я, то, возможно, спрашиваешь "Зачем TypeScript?". Для начала - это хайпово, использовать TypeScript везде, где есть JavaScript: фронтенд, бекенд.
Кроме всего прочего, Typescript позволяет вам добавлять статическую типизацию в ваш проект на Javascript. Это само по себе очень поможет вам поддерживать проекты в долгосрочной перспективе.

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

По мне, так, тот факт, что Vue будет написан на Typescript, пойдет на пользу разработчикам, даже если они продолжат использовать стандартный Javascript.

Так как переписанное ядро Vue использует Typescript, то даже в процессе написания на синтаксисе Javascript будет доступно более полное автодополнение, детальный вывод информации и, в конечном счете, документация прямо внутри вашей IDE. Это поможет избежать большого количества просмотров документации по Vue.

Vue стал суперлегким

В настоящее время VueJS уже достаточно легкий (20 кб gzip). Но команда Vue столкнулась с проблемой: внедрение новых возможностей увеличило размер пакета для каждого пользователя, независимо от того, включает ли он их или нет.

Чтобы исправить это, Vue3 будет намного более модульным. В то время как это увеличивает количество импортов, которые вам понадобятся делать для разработки, однако, это гарантирует, что вы не будете тянуть неиспользуемые библиотеки в ваш проект.

Благодаря исключению нежизнеспособного кода, и модульному структурированию, оценочный размер для Vue 3.0 составляет примерно 10 kb gzip. Конечно, многие библиотеки будут импортированы заново, но это здорово, что мы не вынуждены тянуть их все из коробки.

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

Некоторые ресурсы для изучения Vue3

Честно говоря, я думаю, что команда Vue Core делает такую хорошую работу, прислушиваясь к отзывам сообщества и постоянно предоставляя обновления, что одни из лучших мест для изучения Vue3 - это их официальные посты и документация.

При написании этой статьи я потратил много времени на RFC (Request for Comment) и репозиторий vue 3 github - vue-next (официальный Vue3).

Ты готов???

Если у вас есть какой-либо опыт разработки Vue, то ясно, что обновления, которые появятся в Vue3, сделают его более удобным в использовании и более мощным.

От оптимизации рендеринга до помощи разработчикам в написании более читаемого/поддерживаемого кода, Vue3, кажется, улучшит многие болевые точки, испытываемые в Vue2.
Надеюсь, что эта статья хорошо объяснила что нового в Vue3 и то, как новые функции работают.

Если вы сюда пришли, чтобы узнать, когда Vue3 выйдет, то дата выхода Vue Js 3 next будет в начале 2020 года, более точной даты пока нет.