Несколько недель назад я работал над клиентским проектом, который предполагал значительный редизайн всего их сайта. Сайт представляет собой традиционное серверное веб-приложение: HTTP-сервер обслуживает HTML, сгенерированный из статических шаблонов, заполненных переменными, извлеченными из базы данных.

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

Когда пользователь выбирает категорию доставки «Международная», вместо отображения произвольного текстового поля в форме адреса доставки отображается раскрывающийся список стран

Звучит просто, правда? Изменения в устаревшем приложении редко бывают простыми.

Проблема, с которой я столкнулся, заключалась в том, что на странице подписки уже было несколько сотен строк jQuery, управляющих всевозможными мелочами (удалите форму адреса доставки, если подписка является подарком, переключитесь между штатами и провинциями, если пользователь выберет доставку в США и Канаду. , так далее.). Где-то там мне нужно было добавить слушателя в категорию доставки и сказать ему, чтобы он заменил некоторые div при изменении выбора.

Это было тогда, когда я занервничал.

Я не на 100% уверен в jQuery с самого начала (я поздно начал работать с Javascript). Было приличное количество кода, который объединял строки вместе, чтобы выяснить, на какие идентификаторы div нужно нацелить изменения. Это сделало на удивление трудным создать рабочую модель из тех нескольких сотен строк кода в моей голове.

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

  • React «владеет» рендерингом своих компонентов, поэтому, если вы не используете рендеринг React на стороне сервера, вам нужно, чтобы ваш бэкэнд доставлял пустой div и позволял React помещать свои собственные данные внутрь после загрузки страницы.
  • Чтобы передать данные в React из бэкэнда, вам нужно либо отобразить шаблонный JSON (фу), либо использовать конечную точку JSON (у нас ее нет!)

Я вспомнил, как раньше слышал, что Vue.js - это фреймворк, с которым новичкам легче начать работу, чем с React, и мне стало любопытно.

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

Как это было возможно и почему это сработало?

Простая интеграция с HTML-кодом, отображаемым на сервере

Vue может очень легко интегрироваться с существующим HTML (скажите, пожалуйста, может ли React это сделать!). У меня может быть такой div:

<div id="my-component">
  <form blahblah>
    ...
  </form>
</div>

И подключитесь к нему с помощью Vue вот так:

new Vue({
  el: '#my-component'
  ...
})

Это волшебство! Div уже может существовать в DOM, нарисованный вашим сервером. Vue просто прочитает его, возьмет на себя его рендеринг и сохранит все, что уже есть, как есть! Неважно, кто обслуживает ваш HTML, вы можете оставить свои шаблоны там, где они есть, и по отдельности накладывать интерактивные слои.

Если у меня есть данные для записи в DOM, которые обновляются после загрузки страницы, я могу использовать простой шаблон Vue, подобный этому

<div id="my-component">
  <div class="container>
    {{ my_variable_or_method_in_vue }}
  </div>
</div>

А во Vue:

new Vue({
  el: '#my-component'
  data: { 
    my_variable_or_method_in_vue: 2343 
  }
})

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

Удобные помощники для часто используемых функций

Основная задача включения и выключения div на основе какой-либо переменной становится действительно простой с Vue. Следующий div будет отображаться только в том случае, если переменная my_flag нашего компонента Vue имеет значение true.

<div v-if="my_flag">
 flag specific secret info
</div>

Хотите сохранить div, но вместо этого переключить его свойство display CSS?

<div v-show="my_flag">
 flag specific secret info that MUST stay in the DOM
</div>

Насколько я понимаю, этот стиль пришел из Angular, которым я никогда не пользовался. Довольно приятно заменить код, который просто захватывает div за воротник по всей странице, на что-то, привязанное к логическому значению, и о котором можно легко рассуждать.

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

Я сделал свое первое приложение Vue в качестве клиентского проекта, просто прочитав их документацию по началу работы и попробовав что-то. У них есть замечательный плагин инструментов разработчика Chrome, который помогает с отладкой (прямо как React!)

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

Одна из проблем, с которой я столкнулся, например, заключалась в том, как страница подписки на журнал передавала информацию о ценах клиентской части. Когда пользователь выбирает разные типы подписки, мы показываем на экране «промежуточный итог» (который также отражает их код купона!). Поскольку наше приложение никогда ни для чего не использовало JSON, эта информация была закодирована прямо в форме с использованием таких атрибутов, как data-value="3999" для выбора подписки, например, стоимостью 39,99 долларов США. Наш устаревший JavaScript считывает эти значения, применяет коды купонов, а затем суммирует их и выгружает в div, чтобы пользователь мог их увидеть.

Поскольку с Vue все наши данные должны поступать из компонента, нам нужно каким-то образом загрузить значения в поля данных компонента. Мы не можем отображать шаблонный javascript, поэтому нам также необходимо считывать эти значения из DOM. К счастью, Vue предоставляет способ подключения к произвольным узлам DOM в компоненте с помощью refs (точно так же, как React!) И предоставляет функциональный перехватчик mounted, который вы можете использовать для одноразовой загрузки данных из DOM после того, как компонент загружен.

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

Вот пример смешивания HTML и Javascript вместе:

HTML

{{ subscription_price }} - это шаблон Vue, который отображает данные или функции, определенные в компоненте. Эти значения будут автоматически обновляться, если они или их зависимости изменятся.

<div id='my-component'>
  <form>
    <input data-amount="3999" 
           type="radio" 
           ref="print_individual" /> Print
    <input data-amount="1999" 
           type="radio" 
           ref="digital_individual" /> Digital
    <div>Subtotal: {{ subscription_price }}</div>
    <button type="submit">Submit</button>
  </form>
</div>

Компонент Vue

new Vue({
  el: '#my-component',
  data: {
    prices: {
      digital_individual: 0,
      print_individual: 0
    },
    ...
  },
  computed: {
   subscription_price: function() {
     return this.prices[this.subscription_selection]
    }
  },
  mounted: function() {
    this.prices.print_individual = 
        parseInt(this.$refs.print_individual.dataset.amount);
    this.prices.digital_individual = 
        parseInt(this.$refs.digital_individual.dataset.amount);
  }
})
  • data - это место, где хранится состояние вашего компонента
  • computed - это данные, для определения значения которых требуется выполнение функции.
  • mounted как упоминалось ранее, это специальная функция, которая вызывается один раз, как только компонент загружается в DOM.

Надеюсь, это даст вам некоторое представление о том, как работает модель программирования Vue. Методы и данные можно использовать с помощью простого языка шаблонов во внешнем интерфейсе, чтобы сбрасывать изменяющиеся данные в контейнеры, не беспокоясь о том, когда именно это изменится или кто собирается Измени это.

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

Заключение

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

Попробуйте, если у вас возникли те же проблемы! Я хотел бы услышать о вашем опыте!

Ресурсы