🦉 Проверка пропсов (Props Validation) 🦉
По мере того, как приложение становится сложным, может быть довольно небезопасно определять пропсы неформальным способом. Это приводит к двум проблемам:
- трудно сказать, как следует использовать компонент, глядя на его код.
- небезопасно, легко отправить неправильный пропрс в компонент при рефакторинге компонента, либо одного из его родителей.
Система типов пропсов решает обе проблемы, описывая типы и формы пропса. Вот как это работает в Owl:
- ключ
props
является статическим ключом (поэтому отличается отthis.props
в экземпляре компонента) - это необязательно: для компонента нормально не определять ключ
props
. - пропсы проверяются всякий раз, когда компонент создается/обновляется
- пропсы проверяются только в режиме
dev
(см. страницу конфигурации) - если ключ не соответствует описанию, выдается ошибка
- он проверяет ключи, определенные в (статических)
props
. Дополнительные ключи, предоставленные родителем, вызовут ошибку.
For example:
class ComponentA extends owl.Component {
static props = ['id', 'url'];
...
}
class ComponentB extends owl.Component {
static props = {
count: {type: Number},
messages: {
type: Array,
element: {type: Object, shape: {id: Boolean, text: String }
},
date: Date,
combinedVal: [Number, Boolean]
};
...
}
- это объект или список строк
- список строк - это упрощенное определение пропсов, в котором перечислены
только имена пропсов. Кроме того, если имя заканчивается на
?
, оно считается необязательным. - все пропсы по умолчанию обязательны, если они не определены с помощью
optional: true
(в этом случае проверка выполняется только в том случае, если есть значение) - Допустимые типы:
Number, String, Boolean, Object, Array, Date, Function
и все функции-конструкторы (так что, если у вас есть классPerson
, его можно использовать как тип) - массивы однородны (все элементы имеют одинаковый тип/форму)
Для каждого ключа определение prop
является либо логическим значением,
либо конструктором, либо списком конструкторов, либо объектом:
- булево значение: указывает, что пропс существует и является обязательным.
- конструктор: должен описывать тип, например:
id: Number
описываете пропсid
как число - список конструкторов. В этом случае это означает, что мы допускаем более одного типа.
Например,
id: [Number, String]
означает, чтоid
может быть как строкой, так и числом. - объект. Это дает возможность иметь более выразительное определение. Затем разрешены
(но не обязательны) следующие подключи:
type
: основной тип проверяемого пропсаelement
: если тип былArray
, то ключelement
описывает тип каждого элемента в массиве. Если он не установлен, то мы проверяем только массив, а не его элементы,shape
: если тип былObject
, то ключshape
описывает интерфейс объекта. Если он не установлен, то мы проверяем только объект, а не его элементы,validate
: это функция, которая должна возвращать логическое значение, чтобы определить, является ли значение действительным или нет. Полезно для пользовательской проверки.
Примеры:
// задокументировано только существование этих 3 ключей
static props = ['message', 'id', 'date'];
// size не является обязательным
static props = ['message', 'size?'];
static props = {
messageIds: {type: Array, element: Number}, // список чисел
otherArr: {type: Array}, // просто массив. проверка подэлементов не производится
otherArr2: Array, // тож что и otherArr
someObj: {type: Object}, // просто объект, без внутренней проверки
someObj2: {
type: Object,
shape: {
id: Number,
name: {type: String, optional: true},
url: String
]}, // объект, с ключами id (number), name (string, optional) и url (string)
someFlag: Boolean, // логическое, обязательное (даже если `false`)
someVal: [Boolean, Date], // либо логическое значение, либо дата
otherValue: true, // указывает, что это пропс
kindofsmallnumber: {
type: Number,
validate: n => (0 <= n && n <= 10)
},
size: {
validate: e => ["small", "medium", "large"].includes(e)
},
};