Много свойств или свойство-объект: критерии выбора
Мы используя Vue, разрабатываем компоненты различного рода и условий применения. Одной из ключевых частей любых компонентов — это их интерфейс. Во Vue, передаваемые свойства — являются очень важной, если не самой важной, частью интерфейса компонента.
В ситуации, когда компонент требует множество данных, можно применить несколько способов их передачи. Рассмотрим их.
Набор свойств
Одним из возможных способов — это создать для каждого атомарного значения — отдельное свойство. Посмотрим на код компонента использующий подобный подход:
Шаблон
<template>
<div>
<div>First name: {{ firstName }}</div>
<div>Last name: {{ lastName }}</div>
<div>Birth year: {{ birthYear }}</div>
</div>
</template>
Скрипт
const MIN_BIRTH_YEAR = 1900
export default {
name: 'PersonInfo',
props: {
firstName: {
type: String,
required: true,
validator: firstName => firstName !== ''
},
lastName: {
type: String,
required: true,
validator: lastName => lastName !== ''
},
birthYear: {
type: Number,
required: true,
validator: year => year > MIN_BIRTH_YEAR && year < new Date().getFullYear()
}
}
}
Посмотрим на использование этого компонента
<!-- Other part of html template-->
<PersonInfo
first-name="Jill"
last-name="Smith"
:birth-year="2000"
/>
<!-- Other part of html template-->
Рассмотрим преимущества и недостатки такого подхода
Преимущества
- Все свойства — независимы. При невалидности одного из значений — сообщение об ошибке будет более точным
- Наглядно содержание передаваемых свойств
- "Плоское лучше вложенного"
- Добавление новых необязательных свойств довольно легкое дело: просто добавляем свойство, которое использует параметр
default
props: {
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
birthYear: {
type: Number,
required: true,
validator: year => year > MIN_BIRTH_YEAR && year < new Date().getFullYear()
},
city: {
type: String,
default: 'New York'
}
}
Недостатки
- Достаточно многословный код в родительском компоненте, особенно, когда данные берутся из одного объекта. Пример:
<!-- Other part of html template-->
<PersonInfo
:first-name="person.firstName"
:last-name="person.lastName"
:birth-year="person.birthYear"
/>
<!-- Other part of html template-->
- Многословность в определении свойств (в сравнении с описанием объекта)
Свойство-объект
Существуют ситуации, когда атомарными являются данные не примитивных типов. В заданном примере такими данными может быть объект person
.
Рассмотрим пример:
Шаблон
<template>
<div>
<div>First name: {{ person.firstName }}</div>
<div>Last name: {{ person.lastName }}</div>
<div>Birth year: {{ person.birthYear }}</div>
</div>
</template>
Скрипт
import quartet from 'quartet' // npm validation package
const v = quartet()
const MIN_BIRTH_YEAR = 1900
export default {
name: 'PersonInfo',
props: {
person: {
type: Object,
required: true,
validator: v({
firstName: 'string',
lastName: 'string',
birthYear: v.and(
'safe-integer',
v.min(MIN_BIRTH_YEAR),
v.max(new Date().getFullYear())
)
})
}
}
}
Посмотрим на использование:
<!-- Other part of html template-->
<PersonInfo :person="person"/>
<!-- or (bad) -->
<PersonInfo :person="{ firstName: 'Jill', lastName: 'Smith', birthYear: 2000 }"/>
<!-- Other part of html template-->
Рассмотрим преимущества и недостатки
Преимущества
- Код в родительском компоненте становится короче
- При наличии определённой структуры данных, которая не меняется код становится менее избыточным
Недостатки
- Все значения становятся связанными одним объектом. При невалидности одного из значений — сообщение об ошибке будет говорить о невалидности всего объекта
- При использовании объекта в родительском компоненте: содержание передаваемых данных скрывается за абстракцией этого объекта
- Дополнительный уровень вложенности в компоненте
- Добавление новых необязательных свойств со значениями внутрь объекта невозможно (не знаю как это сделать)
- Для валидации объекта в той же степени, нужно использовать дополнительные инструменты валидации (напр. библиотеку валидации
quartet
)
Выводы
Я пришел к таким выводам:
- использование отдельных свойств — более предпочтительно.
- Использование свойства-объекта допустимо, когда структура данных этого объекта не будет пополнятся дополнительными необязательными полями со значением по умолчанию.
P. S
Буду рад узнать ваши критерии выбора. Какой подход вы используете и почему? В прочем это и есть основная цель написания этой статьи. Может кто из вас знает лучшие практики и их обоснование? Спасибо, что уделили время.
Update 19:26, 16.01.2019
Также существует третий вариант c v-bind. Смотри обсуждение здесь