# Входные параметры

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

# Указание типа входных параметров

До сих пор входные параметры видели только как перечисленные в виде массива строк:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
1

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

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // или любой другой конструктор
}
1
2
3
4
5
6
7
8
9

Это не только документирует компонент, но также предупреждает пользователей в консоли JavaScript браузера, если они передают неправильный тип. Гораздо больше о проверках типов и других валидациях входных параметров узнаете дальше на этой странице.

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

До сих пор встречались с тем, что во входные параметры передавались статические значения, например:

<blog-post title="Как изучить Vue"></blog-post>
1

Также встречались входные параметры, связывающие динамическое значение с помощью v-bind или его сокращения :, например:

<!-- Динамически присваиваем значение переменной -->
<blog-post :title="post.title"></blog-post>

<!-- Динамически присваиваем значение комплексного выражения -->
<blog-post :title="post.title + ' — автор ' + post.author.name"></blog-post>
1
2
3
4
5

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

# Передача чисел

<!-- Несмотря на то, что `42` статическое значение, нам нужен v-bind, -->
<!-- чтобы сообщить Vue, что это выражение JavaScript, а не строка.   -->
<blog-post :likes="42"></blog-post>

<!-- Динамическое присвоение значения переменной. -->
<blog-post :likes="post.likes"></blog-post>
1
2
3
4
5
6

# Передача булевых значений

<!-- Указание входного параметра без значения будет означать `true`. -->
<!-- Если во входных параметрах не указать тип is-published как Boolean, то вместо значения "true" будет пустая строка. -->
<blog-post is-published></blog-post>

<!-- Несмотря на то, что `false` статическое значение, нам нужен v-bind -->
<!-- чтобы сообщить Vue, что это выражение JavaScript, а не строка.     -->
<blog-post :is-published="false"></blog-post>

<!-- Динамическое присвоение значения переменной. -->
<blog-post :is-published="post.currentUserFavorited"></blog-post>
1
2
3
4
5
6
7
8
9
10

# Передача массивов

<!-- Несмотря на то, что указан статический массив, нам нужен v-bind, -->
<!-- чтобы сообщить Vue, что это выражение JavaScript, а не строка.   -->
<blog-post :comment-ids="[234, 266, 273]"></blog-post>

<!-- Динамическое присвоение значения переменной. -->
<blog-post :comment-ids="post.commentIds"></blog-post>
1
2
3
4
5
6

# Передача объектов

<!-- Несмотря на то, что указан статический объект, нам нужен v-bind, -->
<!-- чтобы сообщить Vue, что это выражение JavaScript, а не строка.   -->
<blog-post
  :author="{ name: 'Veronica', company: 'Veridian Dynamics' }"
></blog-post>

<!-- Динамическое присвоение значения переменной. -->
<blog-post :author="post.author"></blog-post>
1
2
3
4
5
6
7
8

# Передача свойств объекта

Если хотите передать все свойства объекта в качестве входных параметров, то можно использовать v-bind без аргументов (v-bind вместо v-bind:prop-name). Например, для объекта post:

post: {
  id: 1,
  title: 'Как изучить Vue'
}
1
2
3
4

Следующий шаблон:

<blog-post v-bind="post"></blog-post>
1

Будет аналогичен такой записи:

<blog-post v-bind:id="post.id" v-bind:title="post.title"></blog-post>
1

# Однонаправленный поток данных

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

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

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

  1. Входной параметр используется для передачи начального значения; дочерний компонент хочет использовать его как локальное свойство данных в дальнейшем. В этом случае лучше всего определить локальное свойство в данных, которое использует значение входного параметра в качестве начального:

    props: ['initialCounter'],
    data() {
      return {
        counter: this.initialCounter
      }
    }
    
    1
    2
    3
    4
    5
    6
  2. Входной параметр передаётся как необработанное значение, которое необходимо преобразовать. В таком случае лучше всего объявить вычисляемое свойство с использованием входного параметра:

    props: ['size'],
    computed: {
      normalizedSize() {
        return this.size.trim().toLowerCase()
      }
    }
    
    1
    2
    3
    4
    5
    6

Совет

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

# Валидация входных параметров

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

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

app.component('my-component', {
  props: {
    // Просто проверка типа (`null` и `undefined` проходят проверку для любого типа)
    propA: Number,
    // Несколько допустимых типов
    propB: [String, Number],
    // Обязательное значение строкового типа
    propC: {
      type: String,
      required: true
    },
    // Число со значением по умолчанию
    propD: {
      type: Number,
      default: 100
    },
    // Объект со значением по умолчанию
    propE: {
      type: Object,
      // Для объектов или массивов значения по умолчанию
      // должны возвращаться из функции
      default() {
        return { message: 'привет' }
      }
    },
    // Пользовательская функция для валидации
    propF: {
      validator(value) {
        // Значение должно соответствовать одной из этих строк
        return ['success', 'warning', 'danger'].includes(value)
      }
    },
    // Функция с значением по умолчанию
    propG: {
      type: Function,
      // В отличие от объекта или массива по умолчанию, это не фабричная функция — это функция, служащая в качестве значения по умолчанию
      default() {
        return 'Функция по умолчанию'
      }
    }
  }
})
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

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

Совет

Обратите внимание, что входные параметры будут валидироваться перед созданием экземпляра компонента, поэтому свойства экземпляра (например, data, computed и т.д.) будут недоступны внутри default или функций validator.

# Проверка типа

Значением type может быть один из следующих нативных конструкторов:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

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

function Person(firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}
1
2
3
4

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

app.component('blog-post', {
  props: {
    author: Person
  }
})
1
2
3
4
5

Для проверки, что значение входного параметра author создано с помощью new Person.

# Регистр в именах входных параметров

Имена HTML-атрибутов не чувствительны к регистру, поэтому любые заглавные символы браузеры будут интерпретировать как строчные. Это значит, что при использовании шаблонов в DOM, входные параметры в camelCase должны быть указаны в kebab-case (разделённые дефисом) эквиваленте:

const app = Vue.createApp({})

app.component('blog-post', {
  // camelCase в JavaScript
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
1
2
3
4
5
6
7
<!-- kebab-case в HTML -->
<blog-post post-title="hello!"></blog-post>
1
2

Опять же, при использовании строковых шаблонов это ограничение не применяется.