Подразумевается, что вы уже изучили и разобрались с разделом Основы компонентов. Если нет — прочитайте его сначала.
Имена HTML-атрибутов являются регистро-независимыми, поэтому обозреватели понимают любые прописные символы как строчные. Это означает, что при использовании шаблонов в DOM входные параметры в camelCase-стиле должны использовать свои эквиваленты в стиле kebab-case (разделённые дефисами):
Vue.component('blog-post', {
// camelCase в JavaScript
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
<!-- kebab-case в HTML -->
<blog-post post-title="hello!"></blog-post>
Опять же, если вы используете строковые шаблоны, то это ограничение не применяется.
До сих пор мы видели только входные параметры, перечисленные в виде массива строк:
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
Однако лучше, когда каждый входной параметр будет определённого типа. В этих случаях вы можете перечислить входные параметры объектом, где свойство и значение будут содержать информацию об имени входного параметра и его типе, соответственно:
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // или любой другой конструктор
}
Это не только документирует ваш компонент, но также предупреждает пользователей в консоли JavaScript обозревателя, если они передают неправильный тип. Вы узнаете гораздо больше о проверках типов и других проверках входных параметров дальше на этой странице.
До сих пор вы встречали, что во входные параметры передавались статические значения, например:
<blog-post title="My journey with Vue"></blog-post>
Вы также встречали входные параметры, присваивающие динамическое значение с помощью v-bind
, например:
<!-- Динамически присваиваем значение переменной -->
<blog-post v-bind:title="post.title"></blog-post>
<!-- Динамически присваиваем значение комплексного выражения -->
<blog-post
v-bind:title="post.title + ' написанный ' + post.author.name"
></blog-post>
В этих двух примерах мы передаём строковые значения, но могут передаваться значения любого типа во входной параметр.
<!-- Несмотря на то, что `42` статическое значение, нам нужен v-bind, -->
<!-- чтобы сообщить Vue, что это выражение JavaScript, а не строка. -->
<blog-post v-bind:likes="42"></blog-post>
<!-- Динамическое присвоение значения переменной. -->
<blog-post v-bind:likes="post.likes"></blog-post>
<!-- Указание входного параметра без значения будет означать `true`. -->
<blog-post is-published></blog-post>
<!-- Несмотря на то, что `false` статическое значение, нам нужен v-bind -->
<!-- чтобы сообщить Vue, что это выражение JavaScript, а не строка. -->
<blog-post v-bind:is-published="false"></blog-post>
<!-- Динамическое присвоение значения переменной. -->
<blog-post v-bind:is-published="post.currentUserFavorited"></blog-post>
<!-- Несмотря на то, что указан статический массив, нам нужен v-bind, -->
<!-- чтобы сообщить Vue, что это выражение JavaScript, а не строка. -->
<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>
<!-- Динамическое присвоение значения переменной. -->
<blog-post v-bind:comment-ids="post.commentIds"></blog-post>
<!-- Несмотря на то, что указан статический объект, нам нужен v-bind, -->
<!-- чтобы сообщить Vue, что это выражение JavaScript, а не строка. -->
<blog-post
v-bind:author="{ name: 'Veronica', company: 'Veridian Dynamics' }"
></blog-post>
<!-- Динамическое присвоение значения переменной. -->
<blog-post v-bind:author="post.author"></blog-post>
Если вы хотите передать все свойства объекта в качестве входных параметров, вы можете использовать v-bind
без аргументов (v-bind
вместо v-bind:prop-name
). Например, для объекта post
:
post: {
id: 1,
title: 'My Journey with Vue'
}
Следующий шаблон:
<blog-post v-bind="post"></blog-post>
Будет аналогичен:
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
Все входные параметры образуют одностороннюю привязку между дочерним свойством и родительским: когда родительское свойство обновляется — оно будет передаваться дочернему, но не наоборот. Это предотвращает случайное изменение дочерними компонентами родительского состояния, что может затруднить понимание потока данных вашего приложения.
Кроме того, каждый раз, когда обновляется родительский компонент, все входные параметры дочернего компонента будут обновлены насущными значениями. Это означает, что вы не должны пытаться изменять входной параметр внутри дочернего компонента. Если вы это сделаете, Vue отобразит предупреждение в консоли.
Обычно встречаются два случая, когда возникает соблазн изменять входной параметр:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
Обратите внимание, что объекты и массивы в JavaScript передаются по ссылке, поэтому если входной параметр является массивом или объектом, то изменение объекта или массива внутри дочернего компонента будет влиять на состояние родителя.
Компоненты могут указывать требования к своим входным параметрам, такие как определение типа, которые вы уже видели. Если эти требования не выполнены — Vue предупредит вас сообщением в JavaScript-консоли обозревателя. Это особенно полезно при разработке компонента, который предназначен для использования другими.
Чтобы указать проверки входного параметра, вы можете предоставить в props
объект с проверками для проверки значения, вместо массива строк. Например:
Vue.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: function () {
return { message: 'hello' }
}
},
// Пользовательская функция для проверки
propF: {
validator: function (value) {
// Значение должно соответствовать одной из этих строк
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
Когда проверка входного параметра заканчивается ошибкой — Vue выдаст предупреждение в консоли (если используется сборка для разработки).
Обратите внимание, что входные параметры проверяются перед созданием экземпляра компонента, поэтому свойства экземпляра (например, data
, computed
и т.д.) не будут доступны внутри default
или функций validator
.
Значением type
может быть один из следующих родных конструкторов:
Кроме того, type
также может быть пользовательской функцией-конструктором и проверка будет выполняться проверкой с помощью instanceof
. Например, если существует следующая функция-конструктор:
function Person (firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
Вы можете использовать:
Vue.component('blog-post', {
props: {
author: Person
}
})
чтобы проверить, что значение входного параметра author
было создано с помощью new Person
.
Обычные атрибуты — это атрибуты, передаваемые в компонент, но не имеющие определения соответствующего входного параметра в компоненте.
Хотя явно определённые свойства предпочтительны для передачи информации дочернему компоненту, авторы библиотек компонентов не всегда могут предвидеть все контексты, в которых будут использованы их компоненты. Вот почему компоненты могут принимать произвольные атрибуты, которые добавляются в корневой элемент компонента.
Например, представьте, что мы используем сторонний компонент bootstrap-date-input
с добавкой Bootstrap, который требует указания атрибута data-date-picker
на элементе input
. Мы можем добавить этот атрибут к нашему экземпляру компонента:
<bootstrap-date-input data-date-picker="activated"></bootstrap-date-input>
И атрибут data-date-picker="activated"
будет автоматически добавлен в корневой элемент bootstrap-date-input
.
Представьте, что это шаблон для bootstrap-date-input
:
<input type="date" class="form-control">
Чтобы добавить тему для нашей добавки выбора даты, нам может понадобиться добавить определённый класс, например:
<bootstrap-date-input
data-date-picker="activated"
class="date-picker-theme-dark"
></bootstrap-date-input>
В этом случае определены два разных значения для class
:
form-control
, который задаётся компонентом в его шаблонеdate-picker-theme-dark
, который передаётся компоненту его родителемДля большинства атрибутов значение, предоставляемое компоненту, будет заменять значение, заданное компонентом. Например, передача type="text"
будет заменять type="date"
и, вероятно, ломать всё! К счастью, работа с атрибутами class
и style
немного умнее, поэтому оба значения будут объединены в итоговое: form-control date-picker-theme-dark
.
Если вы не хотите, чтобы корневой элемент компонента наследовал атрибуты, вы можете установить inheritAttrs: false
в настройках компонента. Например:
Vue.component('my-component', {
inheritAttrs: false,
// ...
})
Это может быть особенно полезно в сочетании со свойством экземпляра $attrs
, которое содержит имена атрибутов и значения, переданные компоненту, например:
{
required: true,
placeholder: 'Введите имя пользователя'
}
С помощью inheritAttrs: false
и $attrs
вы можете вручную определять к какому элементу должны применяться атрибуты, что часто требуется для базовых компонентов:
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})
Обратите внимание, что параметр inheritAttrs: false
не влияет на привязки style
и class
.
Этот шаблон позволяет вам использовать базовые компоненты больше как обычные HTML-элементы, не беспокоясь о том, какой элемент будет у него корневым:
<base-input
label="Пользователь:"
v-model="username"
required
placeholder="Введите имя пользователя"
></base-input>