Филип Раковски
Перевод: сумасшедший технический ботаник
оригинал:v UE school.IO/articles/vu…
Копирование без разрешения строго запрещено
В предыдущей статье мыУзнайте об улучшениях производительности, которые принесет Vue 3. Мы уже знаем, что программы, написанные на новом Vue 3, будут работать хорошо, но производительность — не самая важная часть. Для разработчиков важнее всего то, как новая версия повлияет на то, как мы пишем код.
Как и следовало ожидать, Vue 3 предлагает множество интересных новых функций. К счастью, команда Vue в основном занималась дополнениями и улучшениями текущего API, а не внесением изменений, поэтому люди, уже знакомые с Vue 2, скоро освоятся с новым синтаксисом.
Начнем с API, о котором многие из вас наверняка слышали... Давайте начнем с API, о котором многие из вас, вероятно, слышали...
API композиции
Компонентный API — это наиболее часто обсуждаемый и рекомендуемый синтаксис в следующей основной версии Vue. Это совершенно новый подход к повторному использованию логики и организации кода.
В настоящее время мы создаем наши компоненты, используя так называемый Options API. Чтобы добавить логику к компоненту Vue, мы заполняем (необязательные) свойства, такие какdata
,methods
,computed
Ждать. Самым большим недостатком этого подхода является то, что он сам по себе не является допустимым кодом JavaScript. Вам необходимо точно знать, какие свойства доступны в шаблоне иthis
Поведение ключевых слов. За кулисами компилятору Vue необходимо преобразовать это свойство в рабочий код. Таким образом, мы не можем извлечь выгоду из самовнушения или проверки типов.
API компонентов призван решить эту проблему, предоставляя механизмы, доступные в настоящее время в свойствах компонентов, в виде функций JavaScript. Основная команда Vue описывает API компонента как«Набор дополнительных API-интерфейсов на основе функций для гибкой композиции логики компонентов».Код, написанный с помощью компонентного API, более удобочитаем и не содержит магии, что облегчает его чтение и изучение.
Давайте посмотрим, как это работает, на простом примере компонента, использующего новый API компонента.
<template>
<button @click="increment">
Count is: {{ count }}, double is {{ double }}, click to increment.
</button>
</template>
<script>
import { ref, computed, onMounted } from 'vue'
export default {
setup() {
const count = ref(0)
const double = computed(() => count.value * 2)
function increment() {
count.value++
}
onMounted(() => console.log('component mounted!'))
return {
count,
double,
increment
}
}
}
</script>
Теперь давайте разобьем код на части, чтобы понять, что происходит:
import { ref, computed, onMounted } from 'vue'
Как я упоминал ранее, API компонентов предоставляет свойства компонентов в виде функций, поэтому первым шагом является импорт необходимых функций. В примере нужно использоватьref
Создайте адаптивную ссылку сcomputed
Создайте вычисляемое свойство и используйтеonMounted
Доступ к установленным хукам жизненного цикла.
Теперь вам может быть интересно узнать об этом таинственномsetup
Что именно представляет собой метод?
export default {
setup() {
Короче говоря, это просто функция, которая возвращает свойства и функции в шаблон. Здесь мы объявляем все реактивные свойства, вычисляемые свойства, наблюдатели и обработчики жизненного цикла и возвращаем их, чтобы их можно было использовать в шаблонах.
мы неsetup
Содержимое, возвращаемое функцией, не будет доступно в шаблоне.
const count = ref(0)
Из вышеизложенного заявляем, что сref
имя функцииcount
Свойство ответа. Он может обернуть любой примитив или объект и вернуть его реактивную ссылку. Значение переданного элемента будет сохранено в созданной ссылкеvalue
в свойствах. Например, если вы хотите получить доступcount
ссылочное значение, вам нужно явно запросить егоcount.value
.
const double = computed(() => count.value * 2)
function increment() {
count.value++
}
Это то, что мы вычисляем свойства в заявленииdouble
а такжеincrement
функция делать.
onMounted(() => console.log('component mounted!'))
использоватьonMounted
hook, мы запишем несколько сообщений, когда компонент будет установлен, просто чтобы показать вам, что это можно сделать! 😉
return {
count,
double,
increment
}
Наконец, мы будем использоватьincrement
метод возвращаетcount
а такжеdouble
свойства, чтобы сделать их доступными в шаблоне.
<template>
<button @click="increment">
Count is: {{ count }}, double is {{ double }}. Click to increment.
</button>
</template>
Вуаля! Теперь мы можем получить доступ к шаблону вsetup
Методы возвращают свойства и функции, как если бы они были объявлены через старый API параметров.
Это простой пример, который также можно легко реализовать с помощью API параметров. Реальные преимущества нового компонентного API заключаются не только в возможности кодировать по-другому, эти преимущества также проявляются при повторном использовании нашего кода и логики.
Повторное использование кода с компонентным API
Новый API компонентов имеет больше преимуществ. Подумайте о повторном использовании кода. В настоящее время, если мы хотим поделиться некоторым кодом между другими компонентами, доступны два варианта: миксины и слоты с ограниченной областью действия. Но у обоих есть недостатки.
Допустим, мы хотим извлечьcounter
функции и повторно используются в других компонентах. Ниже вы можете увидеть, как использовать его с доступным API и API нового компонента:
Начнем с миксинов:
import CounterMixin from './mixins/counter'
export default {
mixins: [CounterMixin]
}
Самым большим недостатком примесей является то, что мы ничего не знаем о поведении, которое они на самом деле добавляют к компоненту. Это не только затрудняет понимание кода, но также может привести к конфликтам имен с существующими свойствами и функциями.
Вот слоты с ограниченной областью действия:
<template>
<Counter v-slot="{ count, increment }">
{{ count }}
<button @click="increment">Increment</button>
</Counter>
</template>
Используя слоты с областью видимости, мы точно знаем, что можем передатьv-slot
К каким свойствам обращаются свойства, поэтому код легче понять. Недостатком этого подхода является то, что мы можем получить к нему доступ только в шаблоне и только вCounter
Используется в области компонента.
Теперь пришло время использовать API компонента:
function useCounter() {
const count = ref(0)
function increment () { count.value++ }
return {
count,
incrememt
}
}
export default {
setup () {
const { count, increment } = useCounter()
return {
count,
increment
}
}
}
Это более элегантно? Мы не ограничены рамками шаблона и компонента и точно знаем, к каким свойствам можно получить доступ из counter. Кроме того, мы можем извлечь выгоду из функции завершения кода, доступной в редакторе, потому чтоuseCounter
Просто функция, которая возвращает некоторые свойства, поэтому редактор может помочь нам с проверкой типов и предложениями.
Это также более элегантный способ использования сторонних библиотек. Например, если бы мы хотели использовать Vuex, мы могли бы явно использоватьuseStore
вместо того, чтобы загрязнять прототип Vue (this.$store
). Этот подход также устраняет закулисную магию плагинов Vue.
const { commit, dispatch } = useStore()
Если вы хотите узнать больше об Component API и вариантах его использования, я настоятельно рекомендую вам прочитать команду Vue.эта статья, который объясняет причины нового API и предлагает наилучшие варианты использования. а такжеgreat repository, который содержит пример API компонентов, используемый Торстеном Люнборгом из основной команды Vue.
Глобальные изменения API монтирования/настройки
Мы можем найти еще одно важное изменение в способе создания и настройки программ. Давайте посмотрим, как это работает сейчас:
import Vue from 'vue'
import App from './App.vue'
Vue.config.ignoredElements = [/^app-/]
Vue.use(/* ... */)
Vue.mixin(/* ... */)
Vue.component(/* ... */)
Vue.directive(/* ... */)
new Vue({
render: h => h(App)
}).$mount('#app')
В настоящее время мы используем глобальнуюVue
Объект предоставляет всю конфигурацию и создает новый экземпляр Vue. правильноVue
Любые изменения, внесенные в объект, повлияют на каждый экземпляр и компонент Vue.
Теперь давайте посмотрим, как это работает в Vue 3:
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.config.ignoredElements = [/^app-/]
app.use(/* ... */)
app.mixin(/* ... */)
app.component(/* ... */)
app.directive(/* ... */)
app.mount('#app')
Вы могли заметить, что каждая конфигурация ограничена в использовании.createApp
Определенная программа Vue.
Это может упростить ваш код проще понять, а менее склонны к неожиданным проблемам, вызванным сторонним плагинами. В настоящее время, если некоторые сторонние решения изменяют Vue объекты, то он может быть неожиданным способами (особенно глобальным смесью) влияет на вашу программу, и Vue 3 не является проблемой.
В настоящее время эти изменения APIэтот RFCобсуждается, а это значит, что это может измениться в будущем.
Фрагменты
Еще одно интересное дополнение, которое мы можем ожидать в Vue 3, — это фрагменты.
Какой фрагмент вы могли бы спросить? Что ж, если вы создаете компонент Vue, у него может быть только один корневой узел.
Это означает, что такой компонент не может быть создан:
<template>
<div>Hello</div>
<div>World</div>
</template>
Причина в том, что экземпляр VUE, представляющий любой вариант VUE, должен быть связан в один элемент DOM. Единственный способ создания компонента с несколькими узлами DOM состоит в том, чтобы создать функциональный компонент без основного экземпляра Vue.
Оказывается, у сообщества React такая же проблема. Решением, которое они придумали, был фиктивный элемент под названием Fragment. выглядит так;
class Columns extends React.Component {
render() {
return (
<React.Fragment>
<td>Hello</td>
<td>World</td>
</React.Fragment>
);
}
}
Хотя фрагмент выглядит как обычный элемент DOM, он виртуальный и вообще не отображается в дереве DOM. Это позволяет нам связать функциональность компонента с одним элементом, не создавая избыточных узлов DOM.
Теперь вы можете использоватьvue-fragmentsФрагменты используются в Vue 2 библиотеки, а в Vue 3 вы можете использовать ее напрямую!
Suspense
Еще одна функция, извлеченная из React, которая будет использоваться в Vue 3, — это компоненты Suspense.
Приостановка может приостановить рендеринг вашего компонента и рендеринг вспомогательных компонентов до тех пор, пока не будет выполнено условие. Во время Vue London Юкси Ю кратко затронул эту тему и показал нам, каких API ожидать. Получается, что Suspense — это просто компонент со слотом:
<Suspense>
<template >
<Suspended-component />
</template>
<template #fallback>
Loading...
</template>
</Suspense>
доSuspended-component
Резервный контент будет показан до полного рендеринга. Приостановка может дождаться загрузки компонента (если компонент асинхронный) илиsetup
Функция для выполнения некоторой асинхронной операции.
Multiple v-models
V-модель — это директива, которую можно использовать для реализации двусторонней привязки к данному компоненту. Мы можем передавать реактивные свойства и изменять их внутри компонента.
Мы можем получить хорошее представление об элементах формыv-model
:
<input v-bind="property />
Но вы знаете, что можете использовать его для каждого компонентаv-model
? Внутренний,v-model
просто пройтиvalue
свойства и прослушиваниеinput
Ярлыки к событиям. Переписав приведенный выше пример в следующий синтаксис, вы получите точно такой же эффект:
<input
v-bind:value="property"
v-on:input="property = $event.target.value"
/>
Мы даже можем использовать компонентыmodel
properties, чтобы изменить имена свойств и событий по умолчанию:
model: {
prop: 'checked',
event: 'change'
}
Как видите, если мы хотим сделать ставки на двусторонние привязки в компоненте,v-model
Инструкции могут быть очень полезным синтаксисом. К сожалению, каждый компонент может иметь только одинv-model
.
К счастью, в Vue 3 это не будет проблемой! ты сможешь датьv-model
имена свойств и иметь столько имен свойств, сколько вы хотите. В приведенном ниже примере вы можете найти два компонента формыv-model
:
<InviteeForm
v-model:name="inviteeName"
v-model:email="inviteeEmail"
/>
Изменения в этом API в настоящее времяэтот RFCобсуждение, а это значит, что в будущем могут быть изменения.
Portals
Порталы — это специальные компоненты, используемые для рендеринга чего-либо вне текущего компонента. это такжеРеализовано в Реактодна из функций. Вот что говорится в документации React о порталах:
"Порталы предоставляют уникальный способ визуализации дочерних элементов в узлах DOM за пределами иерархии DOM родительского компонента."
Этот режим обработки является очень хорошим методом, используемым для всплывающих окон и компонентов, которые обычно отображаются в верхней части страницы. Используя порталы, вы можете гарантировать, что никакие правила CSS компонентов хоста не повлияют на компоненты, которые вы хотите отобразить, и вы можете избежать использованияz-index
Произведена хакерская атака.
Для каждого портала нам нужно указать целевое местоположение, в котором будет отображаться содержимое портала. Ниже вы можете получить отportal-vueПосмотрите реализацию в библиотеке, которая добавляет этот функционал в Vue 2:
<portal to="destination">
<p>This slot content will be rendered wherever thportal-target with name 'destination'
is located.</p>
</portal>
<portal-target name="destination">
<!--
This component can be located anywhere in your App.
The slot content of the above portal component wilbe rendered here.
-->
</portal-target>
Vue 3 имеет встроенную поддержку порталов!
Новый API пользовательских директив
Пользовательский API директив будет немного изменен в Vue 3, чтобы лучше соответствовать жизненному циклу компонента. Это улучшение должно сделать API более интуитивно понятным, чтобы новичкам было легче понять и изучить API.
Это текущий API пользовательских директив:
const MyDirective = {
bind(el, binding, vnode, prevVnode) {},
inserted() {},
update() {},
componentUpdated() {},
unbind() {}
}
Вот как это выглядит в Vue 3.
const MyDirective = {
beforeMount(el, binding, vnode, prevVnode) {},
mounted() {},
beforeUpdate() {},
updated() {},
beforeUnmount() {}, // new
unmounted() {}
}
Даже если это серьезное улучшение, оно должно быть легко реализовано в версии, совместимой с Vue.
в этом RFCИзменения в этом API обсуждаются в , что означает, что он может быть улучшен в будущем.
Резюме
В дополнение к Composition API, который является самым крупным новым API в Vue 3, мы можем найти множество небольших улучшений. Видно, что Vue движется к более удобному опыту разработки и более простому и интуитивно понятному API. Приятно видеть, что команда Vue решила использовать многие идеи в основе фреймворка, которые в настоящее время доступны только через сторонние библиотеки.
В приведенном выше списке представлены только основные изменения и улучшения API. Если вам интересен другой контент, обязательно проверьтеРепозиторий Vue RFC.