Хабрахабр

[Перевод] Темный день для Vue.js

Две недели назад создатель Vue Эван Ю опубликовал предложение (RFC) с новым функциональным API для компонентов в грядущем Vue 3. Сегодня я был изумлен тем, как обычно позитивное и дружелюбное сообщество Vue.js скатилось в печальное противостояние. Сегодня критическое обсуждение на Reddit и аналогичные комментарии на Hacker News вызвали наплыв разработчиков в изначальный RFC с возмущениями, порой даже чересчур резкими. 0. Там заявлялось примерно следующее:

  • Весь код на Vue придется переписать совершенно по-новому, потому что существующий синтаксис будет убран
  • Все то время, что люди потратили на изучение Vue, оказалось зря, потому что все поменяется
  • Новый синтаксис оказался хуже старого, не дает внятной структуры и порождает спагетти-код
  • Команда Vue выкатила большое изменение, ни с кем не посоветовавшись
  • Vue превращается в React!
  • Или нет, в AngularJS/Angular!
  • Весь HTML теперь придется писать в одну огромную строку!

В самом деле, самый первый комментарий полон восторгов. После стены негативных комментариев на Reddit вызывает удивление то, что само обсуждение RFC содержит по большей части позитивную реакцию, особенно в числе первых комментариев.

Так вышло, что я получил нотификацию о новом RFC, сразу же прочел его и обнаружил, что это как раз то, чего я бы хотел от Vue 3. Я был человеком, который написал этот первый комментарий. В этом посте я надеюсь раскрыть эту тему, почему я считаю новое API такой хорошей идеей. 0 и написал об этом комментарий в течение 15 минут после публикации RFC, чтобы выразить свою благодарность. Но сперва, позвольте ответить на заявления критиков.

Эван уже добавил туда секцию вопросов и ответов, которая отвечает на большинство вопросов: Подозреваю, что многие люди взбаламутились после прочтения Hacker News или Reddit, где было много недостоверных комментариев, вводящих в заблуждение, но так и не прочли оригинал предложения.

  • Вам не понадобится ничего переписывать с нуля, если вы этого не хотите – новый синтаксис является дополнением, в то время как старый останется с нами на протяжении Vue 3.0 до тех пор, пока его активно используют. Даже если он в итоге будет убран из основного кода, его можно будет легко вернуть обратно с помощью плагинов.
  • Время на обучение Vue не потрачено зря – в новом синтаксисе работают так же, как и раньше, уже знакомые вам концепции, какие как однофайловые компоненты, шаблоны и локальные стили.
  • Изменение не было сделано без обсуждения – этот RFC и есть обсуждение. Новому синтаксису еще далеко до окончательного релиза.
  • И нет, HTML не обязательно нужно писать как огромную строку

Я хочу продемонстрировать это на простом примере, который объяснит почему я настолько в восторге от RFC и почему я думаю, что новый подход приведет к более структурированному коду Был еще несколько субъективный пункт о том, что новый синтаксис порождает менее структурированный код.

При этом: Представьте такой компонент, который дает пользователю ввести информацию о своем питомце и обновляется по мере ввода данных.

  • Текст заголовка обновляется в зависимости от имени питомца
  • Цвет обводки зависит от выбранного цвета животного, включая тень, цвет которой вычисляется на основе выбранного цвета.
  • Размер шрифта заголовка и стиль обводки зависят от выбранного пользователем размера животного

Внешний вид компонента

Вы можете увидеть живое демо с компонентом здесь и также посмотреть исходный код для Vue 2.x вот здесь (файл components/Vue2.vue).

Рассмотрим Javascript-часть этого компонента:

data() ; }, computed: { header: function() { if (this.petName) { return "My Pet " + this.petName; } return "Enter Pet Details"; }, petColorDarker: function() { return tinycolor(this.petColor) .darken() .toString(); }, shadow: function() { return "2px 2px " + this.petColorDarker; }, borderStyle: function() { switch (this.petSize) { case "Small": return "dotted"; case "Medium": return "dashed"; default: return "solid"; } }, headerSize: function() { switch (this.petSize) { case "Small": return "12px"; case "Large": return "60px"; default: return "30px"; } } }

Заметьте, что во Vue 2.x нет способа положить связанные вещи вместе. В принципе, у нас есть какие-то данные и различные свойства, вычисляемые из этих данных. Мы не можем разместить объявление petColor рядом с вычисляемым petColorDarker, потому что во Vue 2.x они группируются по типам.

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

Это похоже на то как вы организуете файлы на своем компьютере – обычно вы не делаете отдельные папки "excel-таблицы" и "word-документы", скорее будут папки "работа" или "планирование отпуска". Новый синтаксис предлагает огранизацию компонентов по связанной функциональности, вместо типа значения. Давайте представим, как будет выглядеть наш компонент в предложенном новом синтаксисе (насколько это получится без возможности запустить код – дайте знать, если найдете какие-то баги):

setup() { // Pet name const petName = value(""); const header = computed(() => { if (petName.value) { return "My Pet " + petName.value; } return "Enter Pet Details"; }); // Pet color const petColor = value("#000"); const petColorDarker = computed(() => { return tinycolor(petColor.value) .darken() .toString(); }); const shadow = computed(() => "2px 2px " + petColorDarker.value); // Pet size const petSize = value(""); const borderStyle = computed(() => { switch (petSize.value) { case "Small": return "dotted"; case "Medium": return "dashed"; default: return "solid"; } }); const headerSize = computed(() => { switch (petSize.value) { case "Small": return "12px"; case "Large": return "60px"; default: return "30px"; } }); // All properties we can bind to in our template return { petName, header, petColor, shadow, petSize, borderStyle, headerSize }; }

Заметим, что:

  • Удивительно просто сгруппировать связанные сущности вместе
  • Глядя на возвращаемое значение функции setup мы сразу видим, к чему у нас есть доступ в шаблоне.

А еще мы можем зарефакторить нашу логику, перенеся в переиспользуемые функции. Кроме того, новый синтаксис предоставляет полную поддержку Typescript, что было трудно достижимо в объектном синтаксисе Vue 2.x. Что-то вроде такого:

function usePetName() { const petName = value(""); const header = computed(() => { if (petName.value) { return "My Pet " + petName.value; } return "Enter Pet Details"; }); return { petName, header };
} function usePetColor() { const petColor = value("#000"); const petColorDarker = computed(() => { return tinycolor(petColor.value) .darken() .toString(); }); return { petColor, petColorDarker };
} function petSizeToBorderStyle(sizeWrapper) { const borderStyle = computed(() => { switch (sizeWrapper.value) { case "Small": return "dotted"; case "Medium": return "dashed"; default: return "solid"; } }); return { borderStyle };
} function petSizeToHeaderSize(petSizeWrapper) { const headerSize = computed(() => { switch (petSizeWrapper.value) { case "Small": return "12px"; case "Large": return "60px"; default: return "30px"; } }); return { headerSize };
} export default { setup() { const { petName, header } = usePetName(); const { petColor, petColorDarker } = usePetColor(); const shadow = computed(() => "2px 2px " + petColorDarker.value); const petSize = value(""); const { borderStyle } = petSizeToBorderStyle(petSize); const { headerSize } = petSizeToHeaderSize(petSize); return { petName, header, petColor, shadow, petSize, borderStyle, headerSize }; }
};

Однако с новым предложенным синтаксисом видно, что можно легко выделить логику из больших компонентов в отдельные кусочки, вынести в отдельные файлы, если нужно, получив маленькие и легкие для понимания функции и компоненты. Во Vue 2.x я часто обнаруживал, что я пишу "монструозный компонент", который сложно разбить на мелкие кусочки – он не может разделиться на меньшие компоненты, потому что слишком много всего происходит на основе небольшого количества переменных состояния.

Скорее всего, нет. Был ли у Vue более темный день? Но у меня есть надежда, что люди взглянут еще раз на RFC, который ничего не ломает, поскольку позволяет людям все так же группировать сущности по типу, если им это нравится, но также позволяет намного больше – более понятный и чистый код, больше возможностей для библиотек и полная поддержка Typescript. Бывшее единым сообщество вокруг проекта раскололось.

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

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть