Vue.js
Реквизит
Поиск…
замечания
camelCase <=> кебаб-чехол
При определении имен ваших props
всегда помните, что имена атрибутов HTML не зависят от регистра. Это означает, что если вы определяете prop
в случае верблюда в определении вашего компонента ...
Vue.component('child', {
props: ['myProp'],
...
});
... вы должны назвать это в своем HTML-компоненте как my-prop.
Передача данных от родителя к ребенку с помощью реквизита
В Vue.js каждый экземпляр компонента имеет свою изолированную область видимости , что означает, что если родительский компонент имеет дочерний компонент, дочерний компонент имеет свою изолированную область, а родительский компонент имеет свою изолированную область.
Для любого приложения от среднего до большого размера в соответствии с рекомендациями по наилучшей практике предотвращается много головных болей на этапе разработки, а затем после технического обслуживания. Одна из таких вещей заключается в том, чтобы избежать ссылок на / исходные данные родительских данных непосредственно из дочернего компонента . Итак, как мы ссылаемся на родительские данные из дочернего компонента?
Независимо от того, какие родительские данные необходимы в дочернем компоненте, он должен быть передан ребенку в качестве props
родителя.
Пример использования . Предположим, у нас есть пользовательская база данных с двумя users
и addresses
таблиц со следующими полями:
таблица users
название | Телефон | Эл. адрес |
---|---|---|
Джон Мклане | (1) 234 5678 9012 | [email protected] |
Джеймс Бонд | (44) 777 0007 0077 | [email protected] |
addresses
таблица
блок | улица | город |
---|---|---|
Башни Накатоми | Бродвей | Нью-Йорк |
Mi6 House | Buckingham Road | Лондон |
и мы хотим иметь три компонента для отображения соответствующей пользовательской информации в любом месте нашего приложения
пользовательский component.js
export default{
template:`<div class="user-component">
<label for="name" class="form-control">Name: </label>
<input class="form-control input-sm" name="name" v-model="name">
<contact-details :phone="phone" :email="email"></contact-details>
</div>`,
data(){
return{
name:'',
phone:'',
email:''
}
},
}
контакт-details.js
import Address from './address';
export default{
template:`<div class="contact-details-component>
<h4>Contact Details:</h4>
<label for="phone" class="form-control">Phone: </label>
<input class="form-control input-sm" name="phone" v-model="phone">
<label for="email" class="form-control">Email: </label>
<input class="form-control input-sm" name="email" v-model="email">
<h4>Address:</h4>
<address :address-type="addressType"></address>
//see camelCase vs kebab-case explanation below
</div>`,
props:['phone', 'email'],
data:(){
return:{
addressType:'Office'
}
},
components:{Address}
}
address.js
export default{
template:`<div class="address-component">
<h6>{{addressType}}</h6>
<label for="block" class="form-control">Block: </label>
<input class="form-control input-sm" name="block" v-model="block">
<label for="street" class="form-control">Street: </label>
<input class="form-control input-sm" name="street" v-model="street">
<label for="city" class="form-control">City: </label>
<input class="form-control input-sm" name="city" v-model="city">
</div>`,
props:{
addressType:{
required:true,
type:String,
default:'Office'
},
data(){
return{
block:'',
street:'',
city:''
}
}
}
main.js
import Vue from 'vue';
Vue.component('user-component', require'./user-component');
Vue.component('contact-details', require'./contact-details');
new Vue({
el:'body'
});
index.html
...
<body>
<user-component></user-component>
...
</body>
Мы показываем данные phone
и email
, которые являются свойствами user-component
в contact-details
которые не содержат телефонных или электронных данных.
Передача данных в виде реквизита
Таким образом, внутри user-component.js
в свойстве шаблона , где мы включаем компонент <contact-details>
, мы передаем телефон и данные электронной почты из <user-component>
(родительский компонент) в <contact-details>
( дочерний компонент), динамически привязывая его к реквизитам - :phone="phone"
и :email="email
который аналогичен v-bind:phone="phone"
и v-bind:email="email"
Опоры - Динамическое связывание
Поскольку мы динамически связываем реквизиты с любыми изменениями в телефоне или электронной почте внутри родительского компонента, то есть <user-component>
будет немедленно отражен в дочернем компоненте, т.е. <contact-details>
.
Реквизит - как литералы
Однако, если бы мы передали значения телефона и электронной почты в виде строковых литералов, таких как phone="(44) 777 0007 0077" email="[email protected]"
то это не отразило бы какие-либо изменения данных, которые происходят в родительском составная часть.
Односторонняя привязка
По умолчанию направление изменений сверху вниз, т.е. любое изменение динамически привязанных реквизитов в родительском компоненте будет распространяться на дочерний компонент, но любое изменение значений prop в дочернем компоненте не будет распространяться на родителя.
Например, если из <contact-details>
мы меняем электронное письмо с [email protected]
на [email protected]
, родительские данные, т. [email protected]
[email protected]
данных телефона в <user-component>
все равно будут содержать значение [email protected]
.
Однако, если мы изменим значение электронной почты от [email protected]
на [email protected]
в родительском компоненте ( <user-component>
в нашем случае использования), то значение электронной почты в дочернем компоненте ( <contact-details>
в нашем случае использования) автоматически изменится на [email protected]
- изменение родительского [email protected]
мгновенно распространяется на ребенка.
Двусторонняя привязка
Если мы хотим двустороннюю привязку, мы должны явно указать двустороннюю привязку как :email.sync="email"
вместо :email="email"
. Теперь, если мы изменим значение prop в дочернем компоненте, изменение будет отражено и в родительском компоненте.
В средстве и крупном приложении изменение состояния родителя из дочернего состояния будет очень сложно обнаружить и отслеживать особенно во время отладки - будьте осторожны .
В Vue.js 2.0 не будет никакой опции .sync. Двусторонняя привязка для реквизита устарела в Vue.js 2.0 .
Одноразовая привязка
Также можно определить явное одноразовое привязку как :email.once="email
, оно более или менее похоже на передачу литерала, потому что любые последующие изменения в значении родительского свойства не будут распространяться на ребенка.
ПРЕДОСТЕРЕЖЕНИЕ
Когда Object или Array передаются как prop, они ВСЕГДА ПРОХОДА ПО ССЫЛКЕ , что означает независимо от типа привязки, явно определенного :email.sync="email"
или :email="email"
или :email.once="email"
, если адрес электронной почты является объектом или массивом в родительском объекте, то независимо от типа привязки любое изменение значения prop в дочернем компоненте также влияет на значение в родительском.
Реквизит в виде массива
В файле contact-details.js
мы определили props:['phone', 'email']
в качестве массива, что прекрасно, если мы не хотим, чтобы мелкозернистый элемент управления с реквизитами.
Реквизит как объект
Если мы хотим более мелкозернистого контроля над реквизитами, например
- если мы хотим определить, какие типы значений приемлемы в качестве опоры
- что должно быть значением по умолчанию для опоры
- является ли значение ДОЛЖНЫ (требуется) для передачи пропеллера или оно необязательно
то нам нужно использовать объектную нотацию для определения реквизита, как это было сделано в address.js
.
Если мы создаем повторно используемые компоненты, которые могут быть использованы другими разработчиками в команде, то хорошей практикой является определение реквизита в качестве объектов, чтобы кто-либо, использующий компонент, имел четкое представление о том, каким должен быть тип данных, и он является обязательным или необязательным.
Он также называется проверкой реквизита . Тип может быть любым из следующих встроенных конструкторов:
- строка
- Число
- логический
- массив
- объект
- функция
- или пользовательский конструктор
Некоторые примеры проверки профайла, взятые из http://vuejs.org/guide/components.html#Props
Vue.component('example', {
props: {
// basic type check (`null` means accept any type)
propA: Number,
// multiple possible types (1.0.21+)
propM: [String, Number],
// a required string
propB: {
type: String,
required: true
},
// a number with default value
propC: {
type: Number,
default: 100
},
// object/array defaults should be returned from a
// factory function
propD: {
type: Object,
default: function () {
return { msg: 'hello' }
}
},
// indicate this prop expects a two-way binding. will
// raise a warning if binding type does not match.
propE: {
twoWay: true
},
// custom validator function
propF: {
validator: function (value) {
return value > 10
}
},
// coerce function (new in 1.0.12)
// cast the value before setting it on the component
propG: {
coerce: function (val) {
return val + '' // cast the value to string
}
},
propH: {
coerce: function (val) {
return JSON.parse(val) // cast the value to Object
}
}
}
});
camelCase против кебаба
HTML-атрибуты нечувствительны к регистру, что означает, что он не может различать addresstype
и addressType
, поэтому при использовании имен propel camelCase в качестве атрибутов нам необходимо использовать их эквиваленты кебаба (дефисграничные):
addressType
должен быть записан как address-type
в атрибуте HTML.
Динамические реквизиты
Так же, как вы можете привязывать данные к представлению к модели, вы также можете связывать реквизиты с помощью той же директивы v-bind для передачи информации от родительского к дочерним компонентам.
JS
new Vue({
el: '#example',
data: {
msg: 'hello world'
}
});
Vue.component('child', {
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>
});
HTML
<div id="example">
<input v-model="msg" />
<child v-bind:my-message="msg"></child>
<!-- Shorthand ... <child :my-message="msg"></child> -->
</div>
Результат
hello world
Передача реквизитов при использовании Vue JSX
У нас есть родительский компонент: импортируя в него дочерний компонент, мы передадим реквизит через атрибут. Здесь атрибут «src», и мы также передаем «src».
ParentComponent.js
import ChildComponent from './ChildComponent';
export default {
render(h, {props}) {
const src = 'https://cdn-images-1.medium.com/max/800/1*AxRXW2j8qmGJixIYg7n6uw.jpeg';
return (
<ChildComponent src={src} />
);
}
};
И дочерний компонент, где нам нужно пройти реквизит. Нам нужно указать, какие реквизиты мы проходим.
ChildComponent.js:
export default {
props: ['src'],
render(h, {props}) {
return (
<a href = {props.src} download = "myimage" >
Click this link
</a>
);
}
};