Руководство для начинающих по работе с компонентами во Vue

В этом руководстве мы рассмотрим работу с компонентами во Vue. Я расскажу, как создавать компоненты, как передавать данные между компонентами. А также как использовать элемент <slot> для рендеринга дополнительного контента внутри компонента.

Как создавать компоненты во Vue

Компоненты — это многократно используемые экземпляры Vue. Существуют разные методы создания компонентов в приложении. К примеру, для регистрации глобального компонента можно использовать способ Vue.component:

Vue.component('my-counter', { data() { return { count: 0 } }, template: `<div>{{ count }}</div>`})new Vue({ el: '#app' })

Имя компонента — my-counter. Его можно использовать следующим образом:

<div id="app"> <my-counter></my-counter></div>

В приведенном выше примере data — это функцию, которая возвращает литерал объекта. Благодаря данному каждый экземпляр компонента получает собственный объект data.

Есть пару методов определения шаблон компонента. В предыдущем примере используется литерал объекта. Но мы также можем использовать тег <script>, встроенный в DOM шаблона.

Однофайловые компоненты

В более сложных проектах глобальные компоненты становятся громоздкими. В таких случаях лучше использовать однофайловые компонентов. Это отдельные файлы с расширением.vue, которые включают в себя разделы <template>, <script> и <style>.

Компонент App может выглядеть следующим образом:

<template> <div id="app"> <my-counter></my-counter> </div></template><script>import myCounter from './components/myCounter.vue'export default { name: 'app', components: { myCounter }}</script><style></style>

А компонент MyCounter может выглядеть так:

<template> <div>{{ count }}</div></template><script>export default { name: 'my-counter', data() {  return {      count: 0    }  }}</script><style></style>

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

В этом руководстве я представлю все примеры с использованием способа регистрации компонента Vue.component().

Передача данных в компоненты через свойства

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

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

<BlogPost>  <AuthorDetails></AuthorDetails>  <PostDetails></PostDetails>  <Comments></Comments></BlogPost>

При этом все данные будут переданы из родительского компонента. Он может выглядеть следующим образом:

new Vue({  el: '#app',  data() {    return {      author: {        name: 'John Doe',        email: 'jdoe@example.com'      }    }  }})

В упомянутом выше компоненте мы определили данные автора и информацию о посте. Далее необходимо создать дочерний компонент. Назовем его author-detail. HTML-шаблон будет выглядеть следующим образом:

<div id="app">  <author-detail:owner="author"></author-detail></div>

Мы передаем дочернему компоненту author объект как свойство с именем owner.  В дочернем компоненте owner- это имя свойства, при помощи которого мы получаем данные из родительского компонента. Данные, которые мы хотим приобрести, называются author. Их мы определили в родительском компоненте.

Чтобы приобрести доступ к данным данным, необходимо объявить свойство в компоненте author-detail:

Vue.component('author-detail', {  template: `    <div>      <h2>{{ owner.name }}</h2>      <p>{{ owner.email }}</p>    </div>  ´,  props: ['owner']})

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

Vue.component('author-detail', {  template: `    <div>      <h2>{{ owner.name }}</h2>      <p>{{ owner.email }}</p>    </div>  `,  props: {    owner: {      type: Object,      required: true    }  }})

Если мы передадим неправильный тип свойства, в консоли отобразится следующая ошибка:

"[Vue warn]: Invalid prop: type check failed for prop 'text'. Expected Boolean, got String.(found in component <>)"

В документации Vue доступно руководство по валидации свойств.

Передача данных от дочернего компонента в родительский через шину событий

События обрабатываются через методы-оболочки, которые запускаются, когда происходит выбранное событие. Давайте расширим пример счетчика, чтобы он увеличивался при каждом нажатии кнопки.

Вот как должен выглядеть компонент:

new Vue({  el: '#app',  data() {    return {      count: 0    }  },  methods: {    increment() {      this.count++    }  }})

Код шаблона:

<div id="app">  {{ count }}  <div>    <button @click="increment">+</button>  </div></div>

Мы подписываемся на событие onClick, чтобы вызывать способ increase при каждом нажатии кнопки. Далее способ increase увеличивает значение переменной count.

Сейчас расширим пример, чтобы переместить кнопку счетчика в отдельный компонент и отобразить счетчик в родительском элементе. Мы можем сделать это при помощи шины событий.

Шины событий полезны, когда необходимо реализовать взаимодействие дочернего компонента с родительским. Вы можете использовать шину событий, если приложение недостаточно велико, чтобы для него требовалось использование Vuex.

Что мы хотим сделать: объект count будет объявлен в родительском компоненте и передан дочернему. Далее в дочернем компоненте увеличивается значение count, а также обновляется значение в родительском компоненте.

Компонент приложения будет выглядеть следующим образом:

new Vue({  el: '#app',  data() {    return {      count: 0    }  }

Далее в дочернем компоненте при помощи свойства получаем значение счетчика и реализуем способ для его увеличения. Мы будем выводить значение count в родительском компоненте:

Vue.component('counter', {  template: `    <div>      <button @click="increment">+</button>    </div>  `,  props: {    value: {      type: Number,      required: true    }  },  methods: {    increment() {      this.count++    }  }})

Тогда наш шаблон будет выглядеть следующим образом:

<div id="app">  <h3>    {{ count }}  </h3>  <counter:count="count" /></div>

Чтобы это сработало, надо отправить событие из дочернего компонента, новое значение count и прослушать это событие в родительском компоненте.

Сначала мы создаем новый экземпляр Vue и присваиваем его константе eventBus:

const eventBus = new Vue();

Сейчас мы можем использовать шину событий в компоненте. Дочерний компонент будет выглядеть следующим образом:

Vue.component('counter', {  props: {    count: {      type: Number,      required: true    }  },  methods: {    increment() {      this.count++      eventBus.$emit('count-incremented', this.count)    }  },  template: `  <div>    <button @click="increment">+</button>  </div>  `})

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

new Vue({  el: '#app',  data() {    return {      count: 0    }  },  created() {    eventBus.$on('count-incremented',(count) => {      this.count = count    })  }})

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

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

Вложение содержимого в компоненты с использованием слотов

Если вы попробуете использовать компонент с закрывающимся тегом и поместите внутрь него содержимое, то Vue заменит его выводом самого компонента:

<div id="app">  <author-detail:owner="author">    <p>This will be replaced</p>  </author-detail></div>

К счастью, слоты Vue могут передавать компоненту произвольное значение. Это может быть что угодно: от элементов DOM до родительского и дочернего компонентов. Давайте посмотрим, как они работают.

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

Vue.component('list', {  template: '#list'})new Vue({  el: "#app"})

Тогда шаблоны будут выглядеть так:

<div id="app">  <h2>Slots</h2>  <list>    <h4>I am the first slot</h4>  </list>  <list>    <h4>I am the second slot</h4>  </list></div><script type="text/x-template" id="list">  <div>    <h3>Child Component</h3>    <slot></slot>  </div></script>

Содержимое компонента <list> выводится между тегами <slot></slot>. Мы также можем использовать запасной контент.

<div id="app">  <h2>Slots</h2>  <list>    <h4>I am the first slot</h4>  </list>  <list></list></div><script type="text/x-template" id="list">  <div>    <h3>Child Component</h3>    <slot>This is fallback content</slot>  </div></script>

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

Заключение

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

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

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