Vue.js
Rekwizyty
Szukaj…
Uwagi
camelCase <=> kebab-case
Podczas definiowania nazw props
zawsze pamiętaj, że w nazwach atrybutów HTML rozróżniana jest wielkość liter. Oznacza to, że jeśli zdefiniujesz prop
w przypadku wielbłąda w definicji komponentu ...
Vue.component('child', {
props: ['myProp'],
...
});
... musisz to nazwać w komponencie HTML jako my-prop.
Przekazywanie danych od rodzica do dziecka za pomocą rekwizytów
W Vue.js każda instancja komponentu ma swój własny izolowany zakres , co oznacza, że jeśli komponent nadrzędny ma komponent podrzędny - komponent podrzędny ma swój izolowany zakres, a komponent nadrzędny ma swój izolowany zakres.
W przypadku aplikacji o średnich i dużych rozmiarach przestrzeganie konwencji najlepszych praktyk zapobiega wielu problemom głowy podczas fazy projektowania, a następnie po konserwacji. Jedną z takich rzeczy do naśladowania jest unikanie odwoływania się / mutowania danych nadrzędnych bezpośrednio z komponentu potomnego . Więc w jaki sposób odwołujemy się do danych nadrzędnych z komponentu podrzędnego?
Wszelkie dane rodzica wymagane w elemencie potomnym należy przekazać dziecku jako props
od rodzica.
Przypadek użycia : Załóżmy, że mamy bazę danych użytkowników z dwoma tabelami users
i addresses
z następującymi polami:
Tabela users
Nazwa | telefon | |
---|---|---|
John Mclane | (1) 234 5678 9012 | [email protected] |
James Bond | (44) 777 0007 0077 | [email protected] |
Tabela addresses
blok | ulica | Miasto |
---|---|---|
Nakatomi Towers | Broadway | Nowy Jork |
Mi6 House | Buckingham Road | Londyn |
i chcemy mieć trzy elementy do wyświetlania odpowiednich informacji o użytkownikach w dowolnym miejscu w naszej aplikacji
user-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:''
}
},
}
contact-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}
}
adres.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>
Wyświetlamy dane phone
i email
- email
, które są właściwościami elementu user-component
w danych contact-details
które nie zawierają danych telefonu ani wiadomości e-mail.
Przekazywanie danych jako rekwizyty
Tak więc w pliku user-component.js
we właściwości szablonu , gdzie uwzględniamy komponent <contact-details>
, przekazujemy telefon i dane e-mail z <user-component>
(komponent nadrzędny) do <contact-details>
( komponent potomny) poprzez dynamiczne wiązanie go z rekwizytami - :phone="phone"
i :email="email
który jest taki sam jak v-bind:phone="phone"
i v-bind:email="email"
Rekwizyty - dynamiczne wiązanie
Ponieważ dynamicznie wiążemy rekwizyty, każda zmiana w telefonie lub e-mailu w komponencie nadrzędnym, tj. <user-component>
zostanie natychmiast odzwierciedlona w komponencie podrzędnym, tj. <contact-details>
.
Rekwizyty - jako literały
Jeśli jednak przekazalibyśmy wartości telefonu i wiadomości e - mail jako wartości literału ciągu, takie jak phone="(44) 777 0007 0077" email="[email protected]"
to nie odzwierciedlałoby to żadnych zmian danych, które nastąpiłyby w rodzicu składnik.
Wiązanie w jedną stronę
Domyślnie kierunek zmian jest od góry do dołu, tj. Każda zmiana dynamicznie związanych rekwizytów w komponencie nadrzędnym zostanie propagowana do komponentu potomnego, ale każda zmiana wartości rekwizytów w komponencie potomnym nie zostanie propagowana do rodzica.
Na przykład: jeśli w <contact-details>
zmienimy wiadomość e-mail z [email protected]
na [email protected]
, dane nadrzędne, tj. Właściwość danych telefonu w <user-component>
nadal będą zawierać wartość [email protected]
.
Jeśli jednak zmienimy wartość wiadomości e-mail z [email protected]
na [email protected]
w elemencie nadrzędnym ( <user-component>
komponent <user-component>
w naszym przypadku użycia), wówczas wartość e-maila w elemencie podrzędnym ( <contact-details>
w naszym przypadku użycia) zmieni się automatycznie na [email protected]
- zmiana rodzica jest natychmiast przenoszona na dziecko.
Wiązanie dwukierunkowe
Jeśli chcemy powiązania dwukierunkowego, musimy jawnie określić powiązanie dwukierunkowe jako :email.sync="email"
zamiast :email="email"
. Teraz, jeśli zmienimy wartość prop w komponencie potomnym, zmiana zostanie odzwierciedlona również w komponencie macierzystym.
W średnich i dużych aplikacjach zmiana stanu nadrzędnego ze stanu podrzędnego będzie bardzo trudna do wykrycia i śledzenia, szczególnie podczas debugowania - bądź ostrożny .
W Vue.js 2.0 nie będzie dostępna żadna opcja .sync. Dwukierunkowe wiązanie rekwizytów jest przestarzałe w Vue.js 2.0 .
Wiązanie jednorazowe
Możliwe jest również zdefiniowanie jednoznacznego jednorazowego wiązania jako :email.once="email
, jest ono mniej więcej podobne do przekazywania literału, ponieważ wszelkie późniejsze zmiany wartości właściwości nadrzędnej nie zostaną przeniesione do potomka.
CAVEAT
Gdy Obiekt lub Tablica są przekazywane jako rekwizyt, są ZAWSZE PRZEKAZANE PRZEZ ODNIESIENIE , co oznacza bez względu na jawnie zdefiniowany typ powiązania :email.sync="email"
lub :email="email"
lub :email.once="email"
, jeśli wiadomość e-mail jest obiektem lub tablicą w obiekcie nadrzędnym, to niezależnie od typu powiązania, każda zmiana wartości prop w komponencie podrzędnym wpłynie również na wartość w obiekcie nadrzędnym.
Rekwizyty jako szyk
W pliku contact-details.js
zdefiniowaliśmy props:['phone', 'email']
jako tablicę, co jest w porządku, jeśli nie chcemy precyzyjnej kontroli rekwizytów.
Rekwizyty jako obiekt
Jeśli chcemy bardziej precyzyjnej kontroli nad rekwizytami, na przykład
- jeśli chcemy zdefiniować, jakie wartości są dopuszczalne jako rekwizyt
- jaka powinna być domyślna wartość dla prop
- czy wartość musi być przekazana dla rekwizytu MUSI (wymagana), czy jest opcjonalna
następnie musimy użyć notacji obiektowej do zdefiniowania rekwizytów, tak jak zrobiliśmy to w address.js
.
Jeśli tworzymy komponenty wielokrotnego użytku, które mogą być również używane przez innych programistów w zespole, dobrą praktyką jest definiowanie rekwizytów jako obiektów, aby każdy, kto korzysta z komponentu, miał jasne pojęcie o tym, jaki powinien być typ danych i czy jest obowiązkowe lub opcjonalne.
Jest również nazywany sprawdzaniem poprawności rekwizytów . Typem może być dowolny z następujących rodzimych konstruktorów:
- Strunowy
- Numer
- Boolean
- Szyk
- Obiekt
- Funkcjonować
- lub niestandardowy konstruktor
Niektóre przykłady sprawdzania poprawności wniosku zaczerpnięte z 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 vs kebab-case
W atrybutach HTML rozróżniana jest addresstype
liter, co oznacza, że nie można rozróżnić między addresstype
a addressType
, dlatego podczas używania nazw addressType
camelCase jako atrybutów musimy używać ich odpowiedników w kebabie (rozdzielanych łącznikami):
addressType
powinien być zapisany jako address-type
w atrybucie HTML.
Dynamiczne rekwizyty
Tak jak jesteś w stanie powiązać dane z widoku do modelu, możesz również powiązać rekwizyty przy użyciu tej samej dyrektywy v-bind do przekazywania informacji z komponentów nadrzędnych do komponentów podrzędnych.
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>
Wynik
hello world
Przekazywanie rekwizytów podczas korzystania z Vue JSX
Mamy komponent nadrzędny: importując komponent podrzędny, przekażemy rekwizyty za pomocą atrybutu. Tutaj atrybut to „src”, a my przekazujemy również „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} />
);
}
};
I element potomny, w którym musimy przekazywać rekwizyty. Musimy określić, które rekwizyty mijamy.
ChildComponent.js:
export default {
props: ['src'],
render(h, {props}) {
return (
<a href = {props.src} download = "myimage" >
Click this link
</a>
);
}
};