- PVSM.RU - https://www.pvsm.ru -

Vue.js tutorial: от jQuery к Vue.js

Привет! Представляю вашему вниманию перевод статьи Vue.js Tutorial: From jQuery to Vue.js [1] автора Paul Redmond [2].

Что касается библиотек JavaScript, то никогда не было более популярной библиотеки, чем jQuery. Она создавалась для обхода DOM элементов с использованием CSS селекторов в то время, когда совместимость браузеров была важной проблемой для разработчиков.

Фактически jQuery настолько универсален, что я подумал что он отлично передаст то, почему я люблю писать UI с Vue, используя компонентный JavaScript. В этом руководстве мы сначала рассмотрим создание пользовательского интерфейса с jQuery, а затем перепишем его с помощью Vue.

Проект

Довольно типично, когда есть форма на которую требуется динамически добавить несколько полей с помощью JavaScript. Представьте, что у нас есть онлайн-форма оформления, которая позволяет пользователю приобретать несколько билетов, для которых требуется имя и адрес электронной почты для каждого билета:

Vue.js tutorial: от jQuery к Vue.js - 1

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

Я создал примеры кода с использованием jQuery [3] и с использованием Vue [4] на Code Pen.

Версия с использованием jQuery

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

Мы могли бы также использовать тег <script type = "text/template"> в качестве шаблона строки и добавить один по умолчанию в DOMContentLoaded, это подход который мы будем использовать.

jQuery HTML Template

Использование шаблона больше соответствует тому, как мы могли бы создать компонент в Vue. Вот как выглядит разметка HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>jQuery Checkout UI</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
    <style type="text/css">
        body {
            margin: 3em
        }

        button {
            cursor: pointer;
        }

        .unit-price {
            margin-right: 2rem;
            color: #999;
        }
    </style>
</head>
<body>
    <div class="container" id="app">
        <form>
            <!-- A placeholder for the list of attendee inputs -->
            <div class="attendee-list"></div>
            <div class="row justify-content-center">
                <div class="col-sm-6"></div>
                <div class="col-sm-2">
                    <button type="button" class="btn btn-secondary add-attendee">Add Attendee</button>
                </div>
            </div>
            <hr>
            <div class="row justify-content-center">
                <div class="col-sm-6">
                    <!-- A placeholder for the unit price -->
                    <span id="unit-price" class="unit-price"></span>
                </div>
                <div class="col-sm-2 text-left">
                    <button type="submit" id="checkout-button" class="btn btn-primary">
                        Pay
                        <!-- A placeholder for the checkout total -->
                        <span class="amount"></span></button>
                </div>
            </div>
        </form>
    </div>

    <script type="text/template" data-template="attendee">
        <div class="attendee row justify-content-center">
            <div class="col-sm-3">
                <div class="form-group">
                <label class="sr-only">Name</label>
                <input 
                    class="form-control"
                    placeholder="Enter name"
                    name="attendees[][name]"
                    required>
                </div>
            </div>
            <div class="col-sm-3">
                <div class="form-group">
                <label class="sr-only">Email address</label>
                <input
                    type="email"
                    class="form-control"
                    placeholder="Enter email"
                    name="attendees[][email]"
                    required>
                </div>
            </div>
            <div class="col-sm-2 text-left">
                <button type="button" class="btn btn-light remove-attendee">
                    <span aria-hidden="true">×</span> Remove
                </button>
            </div>
        </div>
    </script>

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
    <script src="app.js"></script>
</body>
</html>

Мы используем бета-версию Bootstrap 4 для макета. Мы определили несколько заполнителей jQuery, которые будут заполнены данными в $(document).ready(), но из разметки трудно сказать что произойдет. Вам нужно будет смотреть HTML и JavaScript одновременно, чтобы понять смысл предполагаемой функциональности. Возвращение к этому проекту через несколько месяцев потребует приличного количества умственных усилий, чтобы выяснить что происходит.

В нашем файле app.js мы будем заполнять цену за один билет и общую цену, которая будет отображаться с помощью JavaScript на кнопке проверки. Каждый раз, когда пользователь нажимает кнопку «Add Attendee», мы добавим новую строку в контейнер <div class="attendee-list"></div> из шаблона.

Чтобы заполнить список участников повторяющимися полями формы, мы используем тег

Рядом с закрывающим тегом используем последнюю версию jQuery и app.js, в котором мы начнем работу с динамическими обновлениями пользовательского интерфейса.

Инициализация jQuery

Чтобы начать создавать нашу версию с jQuery, давайте инициализируем форму, вычислим общую сумму, добавим строку по умолчанию и установим цену из data:

// app.js

$(document).ready(function () {

    var data = {
        cost: 9.99
    };

    /**
     * Get the attendee count
     */
    function getAttendeeCount() {
        return $('.attendee-list .row.attendee').length;
    }

    function addAttendee() {
        $('.attendee-list').append(
            $('script[data-template="attendee"]').text()
        );
    }

    function syncPurchaseButton() {
        // Total up the count for the checkout button total
        $('#checkout-button span.amount').html(
            '$' + data.cost * getAttendeeCount()
        );
    }

    //
    // Initialize the form
    //

    // Set up the unit cost of one ticket
    $('#unit-price').html('$' + data.cost + ' ea.');

    // Add one attendee by default on init
    addAttendee();
    syncPurchaseButton();
});

Первая часть кода устанавливает литерал [5] объекта data, содержащий одно свойство цены. Цена — это цена одного билета. Возможно, вы захотите установить цену одного билета динамически, но для наших целей она просто захардкожена.

У нас есть несколько вспомогательных функций, включая получение количества участников с помощью DOM query. Использование DOM является единственным точным способом определения этого значения с помощью jQuery.

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

Функция syncPurchaseButton() использует getAttendeeCount() для вычисления и заполнения кнопки покупки конечной суммой.

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

Если вы загрузите страницу в этот момент, форма будет инициализирована одним посетителем, ценой одного билета и общей суммой в кнопке проверки:

Vue.js tutorial: от jQuery к Vue.js - 2

Добавление участников с помощью jQuery

Затем давайте рассмотрим возможность добавления и удаления участников. jQuery имеет отличную обработку событий, включая запуск пользовательских событий. Начнем с кода, необходимого для добавления новых участников:

function addAttendee() {
    $('.attendee-list').append(
        $('script[data-template="attendee"]').text()
    );

    // Sync remove button UI
    syncRemoveButtons();
}

function syncRemoveButtons() {
    // If only one attendee, hide the first remove button
    // otherwise, show all remove buttons
    if (getAttendeeCount() === 1) {
        $('.attendee-list .attendee .remove-attendee').first().hide();
    } else {
        $('.attendee-list .attendee .remove-attendee').show();
    }
}

function syncPurchaseButton() {
    // Total up the count for the checkout button total
    $('#checkout-button span.amount').html(
        '$' + data.cost * getAttendeeCount()
    );
}

// Events
$('.add-attendee').on('click', function (event) {
    event.preventDefault();
    addAttendee();
    $(this).trigger('attendee:add');
}).on('attendee:add', function () {
    syncPurchaseButton();
    syncRemoveButtons();
});

Функция syncRemoveButtons() гарантирует, что пользователь не сможет удалить поле когда оно остаётся только одно, но пользователь может удалить любую строку, если их несколько.

Теперь мы вызываем syncRemoveButtons() в функции addAttendee(), что означает, что если вы обновляете страницу, кнопка удаления скрыта, потому что количество участников — только один.

Обработчик события добавления участника вызывает функцию addAttendee(), а затем запускает пользовательское событие attendee:add.

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

Состояние синхронизации может выйти из-под контроля, так как ваш пользовательский интерфейс jQuery растет. Мы должны явно управлять состоянием и синхронизировать его, когда оно изменяется реагируя на события, и мы должны понимать особенности синхронизации состояний в каждом приложении.

Управление состоянием в jQuery требует дополнительных умственных усилий, потому что его можно обрабатывать и связывать с DOM различными способами. Когда состояние зависит от DOM, а не наоборот, DOM запросы для отслеживания состояния усложняются.

Удаление участников с помощью jQuery

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

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

// Attach an event handler to the dynamic row remove button
$('#app').on('click', '.attendee .remove-attendee', function (event) {
    event.preventDefault();
    var $row = $(event.target).closest('.attendee.row');

    $row.remove();
    $('#app').trigger('attendee:remove');
});

$('#app').on('attendee:remove', function () {
    syncPurchaseButton();
    syncRemoveButtons();
});

Мы добавили click event listener на идентификатор DOM #app, который позволяет нам динамически реагировать на событие click для новых строк. Внутри этого обработчика мы предотвращаем событие кнопки по умолчанию, а затем находим ближайшего предка .row в дереве DOM.

Как только найден родитель $row, мы удаляем его из DOM и запускаем пользовательское событие attendee:remove.

В обработчике события attendee:remove мы синхронизируем нашу кнопку покупки и состояние кнопки удаления.

Готовая jQuery версия

На данный момент у нас есть рабочий jQuery прототип UI нашей формы, который мы можем использовать для сравнения с Vue версией .

Вот полный файл app.js:

$(document).ready(function () {

    var data = {
        cost: 9.99
    };

    /**
     * Get the attendee count
     */
    function getAttendeeCount() {
        return $('.attendee-list .row.attendee').length;
    }

    function addAttendee() {
        $('.attendee-list').append(
            $('script[data-template="attendee"]').text()
        );

        syncRemoveButtons();
    }

    function syncRemoveButtons() {
        // If only one attendee, hide the first remove button
        // otherwise, show all remove buttons
        if (getAttendeeCount() === 1) {
            $('.attendee-list .attendee .remove-attendee').first().hide();
        } else {
            $('.attendee-list .attendee .remove-attendee').show();
        }
    }

    function syncPurchaseButton() {
        // Total up the count for the checkout button total
        $('#checkout-button span.amount').html(
            '$' + data.cost * getAttendeeCount()
        );
    }

    // Events
    $('.add-attendee').on('click', function (event) {
        event.preventDefault();
        addAttendee();
        $(this).trigger('attendee:add');
    }).on('attendee:add', function () {
        syncPurchaseButton();
        syncRemoveButtons();
    });

    // Attach an event handler to the dynamic row remove button
    $('#app').on('click', '.attendee .remove-attendee', function (event) {
        event.preventDefault();
        var $row = $(event.target).closest('.attendee.row');

        $row.remove();
        $('#app').trigger('attendee:remove');
    });

    $('#app').on('attendee:remove', function () {
        syncPurchaseButton();
        syncRemoveButtons();
    });

    //
    // Initialize the form
    //

    // Set up the unit cost of one ticket
    $('#unit-price').html('$' + data.cost + ' ea.');

    // Add one attendee by default on init
    addAttendee();
    syncPurchaseButton();
});

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

JQuery по-прежнему позволяет писать пользовательский интерфейс, но давайте посмотрим как вы можете написать ту же функциональность используя Vue.

Введение в Vue

Большинство людей, вероятно, слышали о Vue на данный момент, но для тех кто не знаком с Vue руководство [6] — отличное место чтобы познакомиться.

Сравнение с другими фреймворками [7] также полезно для восприятия Vue в контрасте с другими фреймворками, с которыми вы, возможно, уже знакомы.

Я предлагаю вам установить расширение Vue devtools [8], доступное в Chrome [9] и Firefox [10]. Инструменты разработчика предоставят вам отличную отладочную информацию, когда вы изучаете и разрабатываете приложения с Vue.

Версия с использованием Vue

Наша версия Vue будет написана с использованием обычного JavaScript, чтобы избежать необходимости беспокоиться об инструментах ES6 и сосредоточиться вместо этого на примере компонента.

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

Начиная

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

Объект-литерал может выглядеть следующим образом:

var data = {
  attendees: [
   { name: 'Example', email: 'user@example.com' }
  ],
  cost: 9.99,
};

Если мы обновим данные, добавив еще одного участника, Vue будет слушать и готов реагировать на это изменение данных:

data.attendees.push({
  name: 'Example 2',
  email: 'user2@example.com'
});

Имея это в виду, давайте построим приблизительную HTML-разметку и JavaScript скелет для нашего пользовательского интерфейса.

Vue HTML шаблон

Мы будем постепенно наращивать JavaScript и HTML, чтобы пропустить вас через каждую функцию, которую мы уже рассмотрели в jQuery версии.

Вот начальная HTML разметка для Vue части этого руководства:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue Checkout UI</title>
    <linkrel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
    <style type="text/css">
        body {
            margin: 3em
        }

        button {
            cursor: pointer;
        }

        .unit-price {
            margin-right: 2rem;
            color: #999;
        }
    </style>
</head>
<body>
  <div class="container" id="app">
    <form>
      <div
        class="row justify-content-center"
        v-for="(attendee, index) in attendees"
        :key="index"
      >
        <div class="col-sm-3">
          <div class="form-group">
            <label class="sr-only">Name</label>
            <input
              class="form-control"
              aria-describedby="emailHelp"
              placeholder="Enter name"
              v-model="attendee.name"
              name="attendees[][name]"
              required
            >
          </div>
        </div>
        <div class="col-sm-3">
          <div class="form-group">
            <label class="sr-only">Email address</label>
            <input
              type="email"
              class="form-control"
              placeholder="Enter email"
              v-model="attendee.email"
              name="attendees[][email]"
              required
            >
          </div>
        </div>
        <div class="col-sm-2 text-left">
          <button type="button" class="btn btn-light">
            <span aria-hidden="true">×</span> Remove</button>
        </div>
      </div>
      <div class="row justify-content-center">
        <div class="col-sm-6"></div>
        <div class="col-sm-2">
          <button type="button" class="btn btn-secondary">Add Attendee</button>
        </div>
      </div>
      <hr>
      <div class="row justify-content-center">
        <div class="col-sm-6">
          <span class="unit-price">${{ cost }} ea.</span>
        </div>
        <div class="col-sm-2 text-left">
          <button type="submit" class="btn btn-primary">Pay</button>
        </div>
      </div>
    <form>
  </div>
  <script src="https://unpkg.com/vue@2.4.4/dist/vue.js"></script>
  <script src="app.js"></script>
</body>
</html>

Разметка очень похожа на нашу jQuery версию, но, возможно, вы заметили переменную для цены одного элемента:

<span class="unit-price">${{ cost }} ea.</span>

Vue использует декларативный рендеринг [11] для рендеринга данных в DOM. {{ cost }} — привязка данных с использованием синтаксиса «Усы» и символа доллара $.

Помните объект данных со свойством cost?

var data = {
  cost: 9.99
};

Тег усы заменяется значением data.cost при изменении связанных данных.

Затем обратите внимание на строку v-for="(attendee, index) in attendees", которая представляет собой цикл, перебирающий массив данных attendees, и отображающий поля ввода формы для каждого участника.

Атрибут v-for — это директива [12], которая «реактивно применяет к DOM изменения при обновлении значения этого выражения». В нашем примере когда массив data.attendees обновлен, DOM будет обновляться в результате действия этой директивы.

Вы должны начать видеть шаблон: мы модифицируем данные (состояние), и пользовательский интерфейс реагирует на эти изменения. В результате ваш код более декларативный и пишется легче.

Инициализация Vue

В нижней части HTML-разметки у нас есть тег, подключающий скрипт app.js с нашим Vue кодом.

Чтобы инициализировать экземпляр Vue на странице, нам нужно подключить Vue к узлу DOM. Мы предоставили контейнер </ div>, что означает что любая разметка внутри этого элемента DOM будет связана с Vue и реагирует на изменение данных:

(function () {
  var app = new Vue({
    el: '#app',
    data: {
      attendees: [{ name: '', email: '' }],
      cost: 9.99,
    },
  });
})();

Мы создаем новый экземпляр Vue, связанный с элементом DOM #app и определяем основной объект данных. Объект данных включает в себя стоимость одного элемента и массив участников. Мы добавили одного пустого участника, так что наша форма по умолчанию будет отображаться с одним набором полей ввода.

Если вы удалите всех участников и сделаете их пустым массивом, вы не увидите никаких имен и сообщений электронной почты.

Все это завернуто в немедленно вызываемое функциональное выражение (IIFE — immediately-invoked function expression), чтобы исключить наш экземпляр из глобальной области.

Расчет общей цены

В jQuery версии мы рассчитали общую цену синхронизируя количество с DOM при помощи события удаления или добавления участника. В Vue, как вы могли догадаться, мы используем data, а затем представление реагирует на эти изменения автоматически.

Мы могли бы сделать что-то вроде следующего, и это будет намного лучше, чем запрос DOM:

<button
  type="submit"
  class="btn btn-primary"
>
  Pay ${{ cost * attendees.length }}
</button>

Тем не менее, слишком много логики в ваших шаблонах делает их менее выразительными и сложными в поддержке. Вместо этого мы можем использовать вычисляемые свойства [13]:

(function () {
  var app = new Vue({
    el: '#app',
    data: {
      attendees: [{ name: '', email: '' }],
      cost: 9.99,
    },
    computed: {
      quantity: function () {
        return this.attendees.length;
      },
      checkoutTotal: function () {
        return this.cost * this.quantity;
      }
    }
  });
})();

Мы определили два вычисляемых свойства. Первое свойство — количество билетов, которое рассчитывается по длине массива attendees.

Второе вычисляемое свойство — checkoutTotal, которое использует первое вычисляемое свойство для умножения количества элементов на стоимость.

Теперь мы можем обновить кнопку проверки используя вычисляемое свойство. Обратите внимание как в результате описано имя вычисленного свойства:

<button
  type="submit"
  class="btn btn-primary"
>
  Pay ${{ checkoutTotal }}
</button>

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

Когда вы добавляете участника, вычисляемое свойство автоматически обновляется и отображается в DOM.

Добавление участнииков с Vue

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

В jQuery мы использовали обработчик событий DOM:

$('.add-attendee').on('click', function () {});

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

Вы можете использовать v-on:click="addAttendee":

<!-- Using v-on: -->
<button
  type="button"
  class="btn btn-secondary"
  v-on:click="attendees.push({ name: '', email: ''})"
>
  Add Attendee
</button>

Или сокращённый вариант click [14]=”addAttendee”:

<!-- Using @click -->
<button
  type="button"
  class="btn btn-secondary"
  @click="attendees.push({ name: '', email: ''})"
>
  Add Attendee
</button>

Нормально использовать любой стиль, но хорошая практика придерживаться одного метода. Я предпочитаю сокращённый стиль.

Когда кнопка нажата, мы помещаем новый объект в массив attendees в шаблоне. Я хотел показать вам этот стиль, чтобы вы могли понять, что вы можете просто запустить JavaScript в атрибуте.

В большинстве случаев лучше использовать обработчики событий, потому что, как правило, события имеют более сложную логику, связанную с ними:

<button
  type="button"
  class="btn btn-secondary"
  @click="addAttendee"
>
  Add Attendee
</button>

Vue принимает свойства методов в основной объект Vue (и в компоненты), что позволяет нам определить метод обработчика событий:

(function () {
  var app = new Vue({
    el: '#app',
    data: {
      attendees: [{ name: '', email: '' }],
      cost: 9.99,
    },
    computed: {
      quantity: function () {
        return this.attendees.length;
      },
      checkoutTotal: function () {
        return this.cost * this.quantity;
      }
    },
    methods: {
      addAttendee: function (event) {
        event.preventDefault();
        this.attendees.push({
          name: '',
          email: '',
        });
      }
    }
  });
})();

Мы предотвращаем действие по умолчанию и помещаем новый объект на массив attendees. Теперь, если вы добавите участников, вы увидите новые добавленные поля ввода, а checkoutTotal будет соответствовать количеству строк:

Vue.js tutorial: от jQuery к Vue.js - 3

Обратите внимание, что обработчик получает объект события, который мы можем использовать для предотвращения действия по умолчанию. Для предотвращения действие события по умолчанию или прекращение распространения (event.stopPropagation()) Vue предоставляет модификаторы событий [15], используемые с точкой (.) как часть атрибута:

<button
  type="button"
  class="btn btn-secondary"
  @click.prevent="addAttendee"
>
  Add Attendee
</button>

Ваши методы ориентированы на данные, а Vue автоматически обрабатывает события DOM с помощью модификаторов событий.

Удаление участников с Vue

Удаление участников похоже на их добавление, но вместо добавления объекта к массиву нам нужно удалить его на основе индекса массива в другом обработчике событий:

<button
  type="button"
  class="btn btn-light"
  @click.prevent="removeAttendee(index)"
>
  <span aria-hidden="true">×</span>
  Remove
</button>

Мы используем индекс массива чтобы ссылаться на нужного посетителя, которого хотим удалить. Если вы вспомните в нашем цикле v-for, мы определили индекс:

<div
  class="row justify-content-center"
  v-for="(attendee, index) in attendees"
  :key="index"
>
  <!-- Attendee inputs -->
</div>

Внутри экземпляра Vue мы определяем метод removeAttendee, который использует splice для удаления одного элемента из массива на основе индекса:

methods: {
  removeAttendee: function (index) {
    this.attendees.splice(index, 1);
  },
  // ...
}

С помощью обработчика removeAttendee вы можете добавлять и удалять участников!

Мы также хотим соответствовать бизнес-требованиям c отображением кнопки «Remove» только при добавлении нескольких участников. Мы не хотим разрешать пользователю удалять все входы.

Мы можем сделать это со встроенной условной директивой v-show [16]:

<button
  type="button"
  class="btn btn-light"
  @click.prevent="removeAttendee(index)"
  v-show="quantity > 1"
>
  <span aria-hidden="true">×</span>
  Remove
</button>

Мы использовали вычисляемое свойство quantity чтобы показать кнопку удаления, когда количество больше единицы.

Мы могли бы также спрятать кнопку с условием v-if. Я рекомендую прочитать документацию, чтобы понять нюансы того, как они работают.

В нашем случае мы используем v-show, чтобы показать и скрыть кнопку с помощью CSS. Если вы измените код с использованием v-if и взглянете на DOM, вы увидите что Vue удаляет элемент из DOM.

Готовая Vue версия

Вот окончательная Vue версия:

(function () {
  var app = new Vue({
    el: '#app',
    data: {
      attendees: [{ name: '', email: '' }],
      cost: 9.99,
    },
    computed: {
      quantity: function () {
        return this.attendees.length;
      },
      checkoutTotal: function () {
        return this.cost * this.quantity;
      }
    },
    methods: {
      removeAttendee: function (index) {
        this.attendees.splice(index, 1);
      },
      addAttendee: function (event) {
        event.preventDefault();
        this.attendees.push({
          name: '',
          email: '',
        });
      }
    }
  });
})();

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

Разметка Vue версии более выразительна в передаче функциональности компонента, чем в jQuery версии. Невозможно определить, какие элементы будут обрабатывать события, прикрепленные в jQuery версии. Кроме того, мы не можем предвидеть, как UI будет реагировать на изменение от разметки HTML.

Что дальше?

Если у вас еще нет опыта работы с Vue, я рекомендую вам прочитать руководство [6] в конце концов. Как и документация Laravel, руководство читается как книга. В документации вы пройдёте через все, что вам нужно, чтобы начать использовать Vue.

От переводчика:

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

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

Сильно не ругайте — это мой первый перевод.

Автор: Алексей Родионов

Источник [17]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/267652

Ссылки в тексте:

[1] Vue.js Tutorial: From jQuery to Vue.js: https://laravel-news.com/jquery-vue

[2] Paul Redmond: https://laravel-news.com/@paulredmond

[3] с использованием jQuery: https://codepen.io/paulredmond/pen/KXegwb

[4] с использованием Vue: https://codepen.io/paulredmond/pen/XeYKLv

[5] литерал: https://ru.wikipedia.org/wiki/%D0%9B%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D0%BB_(%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)

[6] руководство: https://ru.vuejs.org/v2/guide/index.html

[7] Сравнение с другими фреймворками: https://ru.vuejs.org/v2/guide/comparison.html

[8] Vue devtools: https://github.com/vuejs/vue-devtools

[9] Chrome: https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd

[10] Firefox: https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/

[11] декларативный рендеринг: https://ru.vuejs.org/v2/guide/index.html#Декларативный-рендеринг

[12] директива: https://ru.vuejs.org/v2/guide/syntax.html#Директивы

[13] вычисляемые свойства: https://ru.vuejs.org/v2/guide/computed.html

[14] click: https://habrahabr.ru/users/click/

[15] модификаторы событий: https://ru.vuejs.org/v2/guide/events.html#Модификаторы-событий

[16] встроенной условной директивой v-show: https://ru.vuejs.org/v2/guide/conditional.html#v-show

[17] Источник: https://habrahabr.ru/post/341798/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox