От автора: Vue 3 официально еще не вышел, но команда авторов выпустила для нас, разработчиков, альфа-версию, чтобы уже использовать некоторые функции, которые будут поставляться с Vue 3.
На момент написания этой статьи у нас была для экспериментов версия (Alpha-10). Хотя она еще не готова к использованию в производственной среде, всегда полезно заранее изучить новые функции, чтобы после выпуска стабильной версии мы могли напрямую начать использовать ее или перевести существующие приложения Vue 2 на версию 3.0 и использовать новейшие функции.
Настройка
Мы будем использовать установку на основе WebPack. Для этого клонируйте этот репозиторий:
1 2 |
git clone //github.com/vuejs/vue-next-webpack-preview.git vue-next cd vue-next |
Теперь установите пакеты:
1 |
npm install |
Вот и все. У вас сейчас есть рабочий проект Vue 3. Чтобы запустить приложение, просто выполните следующее:
1 |
npm run dev |
Откройте в браузере localhost:8080, и вы увидите простое приложение счетчика.
Откройте файл package.json, здесь вы можете увидеть версию Vue. На момент написания статьи это версия 3.0.0-alpha.8. Откройте App.vue, и вы увидите метод setup(), т. е. Composition API уже используется здесь. Мы можем увидеть некоторые ошибки линтов из официального плагина Vue eslint-plugin-vue, потому что линтеры еще не обновлены, чтобы они могли понимать новый синтаксис.
Прежде чем мы начнем кодировать, давайте рассмотрим новые функции Vue 3.
Новые функции Vue 3
Vue 3 быстрее, меньше по размеру и оснащен лучшей поддержкой TypeScript. Некоторые из новых функций, которые мы можем рассмотреть и научиться реализовывать, включают:
Composition API (теперь встроенный)
Несколько корневых элементов (синтаксис шаблона)
Suspense
Несколько V-моделей
Лучшая реактивность
Порталы
Composition API
Composition API был запущен как плагин несколько месяцев назад, поэтому в нем нет ничего нового, но в Vue 3 нам больше не нужно устанавливать его как плагин. Теперь он встроен в пакет и может использоваться из коробки без каких-либо дополнительных настроек.
Существует два основных преимущества использования Composition API:
Лучшая организация
Совместное / повторное использование кода
Vue 3 по-прежнему будет поддерживать Options API, поэтому, если вы считаете, что вам не нужен Composition API, вы всегда можете использовать традиционные методы из Vue 2. Если вы не знакомы с Composition API, вот как мы можем использовать его для реализации компонента:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<template> <div class="counter"> <p>count: {{ count }}</p> <p>NewVal (count + 2): {{ countDouble }}</p> <button @click="inc">Increment</button> <button @click="dec">Decrement</button> <p> Message: {{ msg }} </p> <button @click="changeMessage()">Change Message</button> </div> </template> <script> import { ref, computed, watch } from 'vue' export default { setup() { /* ---------------------------------------------------- */ let count = ref(0) const countDouble = computed(() => count.value * 2) watch(count, newVal => { console.log('count changed', newVal) }) const inc = () => { count.value += 1 } const dec = () => { if (count.value !== 0) { count.value -= 1 } } /* ---------------------------------------------------- */ let msg= ref('some text') watch(msg, newVal => { console.log('msg changed', newVal) }) const changeMessage = () => { msg.value = "new Message" } /* ---------------------------------------------------- */ return { count, inc, dec, countDouble, msg, changeMessage } } } </script> |
А вот эквивалентный код в Options API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<template> <div class="counter"> <p>count: {{ count }}</p> <p>NewVal (count + 2): {{ countDouble }}</p> <button @click="inc">Increment</button> <button @click="dec">Decrement</button> <p> Message: {{ msg }} </p> <button @click="changeMessage()">Change Message</button> </div> </template> <script> export default { data() { return { count: 0, msg: 'some message' } }, computed: { countDouble() { return this.count*2 } }, watch: { count(newVal) { console.log('count changed', newVal) }, msg(newVal) { console.log('msg changed', newVal) } }, methods: { inc() { this.count += 1 }, dec() { if (this.count !== 0) { this.count -= 1 } }, changeMessage() { msg = "new Message" } } } </script> |
Мы видим, что использование Composition API позволяет лучше организовать код, объединяя отдельные функции (состояние, методы, вычисляемые свойства, наблюдатели и т. д.), что было невозможно в Options API.
В приведенном выше примере код для counter и код для изменения message четко разделены в Composition API. По мере увеличения размера компонента, организация кода становится важным фактором. Любой новый разработчик может легко понять код, не тратя слишком много времени на анализ всех строк.
Раньше мы могли использовать Mixins для обмена кодом. Однако было трудно отслеживать состояния и методы в разных компонентах, и Mixins мог перезаписать существующее состояние или методы в компонентах, если мы не были бы осторожны. Использование Composition API значительно облегчает совместное использование кода. Мы можем выделить код для конкретной функции и использовать его в нескольких местах, как показано ниже:
1 2 3 4 5 6 7 8 9 10 11 12 |
//message.js import { ref, watch } from 'vue' export function message() { let msg = ref(123) watch(msg, newVal => { console.log('msg changed', newVal) }) const changeMessage = () => { msg.value = 'new Message' } return { msg, changeMessage } } |
Использование общего кода в компоненте:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<template> <div class="counter"> <p>count: {{ count }}</p> <p>NewVal (count + 2): {{ countDouble }}</p> <button @click="inc">Increment</button> <button @click="dec">Decrement</button> <p>Message: {{ msg }}</p> <button @click="changeMessage()">change message</button> </div> </template> <script> import { ref, computed, watch } from 'vue' import { message } from './common/message' export default { setup() { let count = ref(0) const countDouble = computed(() => count.value * 2) watch(count, newVal => { console.log('count changed', newVal) }) const inc = () => { count.value += 1 } const dec = () => { if (count.value !== 0) { count.value -= 1 } } let { msg, changeMessage } = message() return { count, msg, changeMessage, inc, dec, countDouble } } } </script> |
Обратитесь к официальному руководству по Composition API для получения более подробной информации.
Несколько корневых элементов (синтаксис шаблона)
Во Vue 2 тег шаблона может принимать только один корневой элемент. Даже если у нас было всего два тега <p>, нам нужно было заключить их в тег div, чтобы это работало. Из-за этого нам также приходилось изменять код CSS в родительском компоненте, чтобы он выглядел так, как ожидалось.
Во Vue 3 это ограничение снято. Больше нет необходимости в корневом элементе.
Мы можем использовать любое количество тегов прямо внутри раздела <template></template>:
1 2 3 4 5 |
<template> <p> Count: {{ count }} </p> <button @click="increment"> Increment </button> <button @click="decrement"> Decrement</button> </template> |
Эквивалентный код Vue 2:
1 2 3 4 5 6 7 |
<template> <div class="counter"> <p> Count: {{ count }} </p> <button @click="increment"> Increment </button> <button @click="decrement"> Decrement</button> </div> </template> |
Suspense
Suspense — это новая функция, которая отображает компонент по умолчанию / резервный компонент, пока основной компонент не извлечет данные.
Иногда мы используем асинхронные операции для получения данных с сервера. Вместо того, чтобы передавать шаблон v-if и затем возвращать его, когда мы вернем данные, Suspense сделает это за нас. Suspense может использоваться как для частей шаблона, так для всего шаблона:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<template> <Suspense> <template #default> <div v-for="item in articleList" :key="item.id"> <article> <h2>{{ item.title }}</h2> <p>{{ item.body }}</p> </article> </div> </template> <template #fallback> Articles loading... </template> </Suspense> </template> <script> import axios from 'axios' export default { async setup() { let articleList = await axios .get('//jsonplaceholder.typicode.com/posts') .then(response => { console.log(response) return response.data }) return { articleList } } } </script> |
Несколько V-моделей
Мы все знаем, что v-модель используется для двусторонней привязки. В основном мы используем ее с элементами формы. Иногда мы даже используем его с пользовательскими компонентами.
Vue 2 допускает использование только одной v-модели на компонент. Во Vue 3 мы можем связать с пользовательскими компонентами любое количество v-моделей:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<template> <survey-form v-model:name="name" v-model:age="age"> </survey-form> </template> //SurveyForm.vue <template> <div> <label>Name: </label> <input :value="name" @input="updateName($event.target.value)" /> <label>Age: </label> <input :value="age" @input="updateAge($event.target.value)" /> </div> </template> <script> export default { props: { name: String, age: Number }, setup(props, { emit }) { const updateName = value => { emit('update:name', value) } const updateAge = value => { emit('update:age', +value) } return { updateName, updateAge } } } </script> |
Лучшая реактивность
У Vue 2 уже была отличная реактивность, и вам, возможно, не приходилось сталкиваться с ситуациями, когда реактивность была недостаточной. Однако было несколько случаев, когда Vue 2 давал сбой. Давайте вернемся к Vue 2 и посмотрим, что это были за ограничения.
Чтобы продемонстрировать реактивность, мы будем использовать наблюдатели, чтобы прослушать одну из переменных состояния, а затем изменим ее, чтобы увидеть запущены ли watcher:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<template> <div class="hello" @click="test">test {{list }} {{ myObj }}</div> </template> <script> export default { name: "HelloWorld", data() { return { list: [1, 2], myObj: { name: "Preetish" } }; }, watch: { list: { handler: () => { console.log("watcher triggered"); }, deep: true } }, methods: { test() { this.list[2] = 4; this.myObj.last = "HS"; delete this.myObj.name; } } }; </script> |
Ни одна из трех вышеперечисленных модификаций, таких как добавление нового элемента в массив на основе индекса, добавление нового элемента в объект или удаление элемента из объекта, не является реактивной во Vue 2. Следовательно watcher не сработает, или DOM будет обновлен. Мы должны были использовать методы vue.set() или vue.delete().
Во Vue 3 они работают напрямую без каких-либо вспомогательных функций:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
export default { setup() { let list = ref([1, 2]) let a = ref(0) let myObj = ref({ name: 'Preetish' }) function myFun() { list.value[3] = 3 myObj.value.last = 'HS' delete myObj.value.name } return { myFun, list, myObj } } } |
Мы можем видеть, что watcher был запущен все четыре раза в настройке Vue 3.
Глобальное монтирование
При открытии main.js в проекте about, вы заметите, что-то отличное. Мы больше не используем экземпляр Global Vue для установки плагинов и других библиотек. Вместо этого вы можете увидеть метод createApp:
1 2 3 4 5 6 7 |
import { createApp } from 'vue' import App from './App.vue' const myApp = createApp(App) myApp.use(/* plugin name */) myApp.use(/* plugin name */) myApp.use(/* plugin name */) myApp.mount('#app') |
Преимущество этой функции в том, что она защищает приложение Vue от сторонних используемых нами библиотек / плагинов, которые могут переопределять или вносить изменения в глобальный экземпляр — в основном с помощью Mixins.
Теперь с помощью метода createApp мы устанавливаем эти плагины для конкретного экземпляра, а не на глобального объекта.
Порталы
Портал — это функция, с помощью которой мы можем визуализировать часть кода, присутствующего в одном компоненте, в другой компонент в другом дереве DOM. Во Vue 2 для этого был сторонний плагин под названием portal-vue.
Во Vue 3 портал будет встроен, и им очень легко пользоваться. Во Vue 3 будет специальный тег <Teleport>, и любой код, заключенный в этот тег, будет готов для телепортации куда угодно. Тег Teleport принимает аргумент to. Давайте рассмотрим это в действии:
1 2 3 4 5 |
<Teleport to="#modal-layer"> <div class="modal"> hello </div> </Teleport> |
Любой код внутри <Portal></Portal> будет отображаться в указанном целевом местоположении.
1 |
<div id="modal-target"></div> |
На момент написания этой статьи <Teleport> не работает в упомянутой выше альфа-версии.
Заключение
Если вы планируете начать свой новый проект, вы все равно можете использовать Vue 2 с плагином Composition API, а затем перейти на Vue 3, так как не будет никаких серьезных изменений, кроме удаления фильтров.
Во Vue 3 будет введено множеством новых и удивительных функций. Интегрированная композиция окажет значительное влияние на процесс разработки, предоставляя простой способ организации и совместного использования кода с отличной поддержкой TypeScript.
Производительность будет точно улучшена, а размер пакета в новом обновлении еще больше уменьшится. Другие функции, такие как Suspense, несколько V-моделей и т.д., сделают разработку проще, чем раньше.
Испытайте свои приложения Vue именно так, как пользователь
Отладка приложений Vue.js может быть затруднена, особенно когда существуют десятки, если не сотни мутаций во время сеанса. Если вы заинтересованы в мониторинге и отслеживании мутаций Vue для всех пользователей, попробуйте LogRocket.
LogRocket похож на видеорегистратор для веб-приложений, он записывает буквально все, что происходит в приложениях Vue, включая сетевые запросы, ошибки JavaScript, проблемы с производительностью и многое другое. Вместо того, чтобы гадать, почему возникают проблемы, вы можете агрегировать и сообщать, в каком состоянии было приложение, когда возникла проблема.
Плагин LogRocket Vuex регистрирует мутации Vuex в консоли LogRocket, предоставляя контекст, который привел к ошибке, и в каком состоянии было приложение, когда возникла проблема. Модернизируйте методы отладки приложений Vue — начните мониторинг бесплатно.
Автор: Preetish HS
Источник: //blog.logrocket.com
Редакция: Команда webformyself.