Vue.js
Rekvisita
Sök…
Anmärkningar
camelCase <=> kebab-fodral
När du definierar namnen på dina props
alltid komma ihåg att HTML-attributnamn är okänsliga för versaler. Det betyder att om du definierar en prop
i kamelfall i din komponentdefinition ...
Vue.component('child', {
props: ['myProp'],
...
});
... du måste kalla det i din HTML-komponent som min-prop.
Vidarebefordra data från förälder till barn med rekvisita
I Vue.js har varje komponentinstans sitt eget isolerade omfång , vilket innebär att om en överordnad komponent har en underordnad komponent - har barnkomponenten sitt eget isolerade omfång och överordnade komponenten har sitt eget isolerade omfång.
För alla apper med medelstor till stor storlek förhindrar det att följa konventioner om bästa praxis massor av huvudvärk under utvecklingsfasen och sedan efter underhåll. En av sådana saker att följa är att undvika att hänvisa till / mutera förälderdata direkt från barnkomponenten . Så hur hänvisar vi till förälderdata från en barnkomponent?
Oavsett förälderdata som krävs i en barnkomponent bör överföras till barnet som props
från föräldern.
Använd fall : Anta att vi har en users
med två tabeller users
och addresses
med följande fält:
users
tabell
namn | telefon | e-post |
---|---|---|
John Mclane | (1) 234 5678 9012 | [email protected] |
James Bond | (44) 777 0007 0077 | [email protected] |
addresses
tabell
blockera | gata | stad |
---|---|---|
Nakatomi Towers | Broadway | New York |
Mi6 House | Buckingham Road | London |
och vi vill ha tre komponenter för att visa motsvarande användarinformation var som helst i vår app
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:''
}
},
}
kontakt-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>
Vi visar phone
och email
postdata, som är egenskaperna för user-component
i contact-details
som inte har telefon- eller e-postdata.
Vidarebefordra data som rekvisita
Så inom user-component.js
i mallegenskapen , där vi inkluderar <contact-details>
-komponenten, överför vi telefonen och e- postdata från <user-component>
(moderkomponent) till <contact-details>
( underordnad komponent) genom att dynamiskt binda den till rekvisita - :phone="phone"
och :email="email
som är samma som v-bind:phone="phone"
och v-bind:email="email"
Rekvisita - dynamisk bindning
Eftersom vi dynamiskt binder rekvisita kommer alla förändringar i telefon eller e-post inom moderkomponenten, dvs <user-component>
omedelbart återspeglas i underordnade komponenter, dvs <contact-details>
.
Rekvisita - som bokstäver
Men om vi skulle ha gått värdena på telefon och e-post som sträng bokstavliga värden som phone="(44) 777 0007 0077" email="[email protected]"
skulle det inte återspegla några dataförändringar som inträffar i överordnade komponent.
Envägsbindande
Som standard är ändringarnas riktning från topp till botten, dvs varje ändring av dynamiskt bundna rekvisita i överkomponenten kommer att spridas till underkomponenten men alla ändringar i prop-värdena i en underordnad komponent sprids inte till överordnade.
Till exempel: om vi från <contact-details>
ändrar e-postmeddelandet från [email protected]
till [email protected]
, kommer överordnad data, dvs. telefondataegenskap i <user-component>
, fortfarande att innehålla ett värde av [email protected]
.
Men om vi ändrar värdet på e-post från [email protected]
till [email protected]
i [email protected]
( <user-component>
i vårt användningsfall) kommer värdet på e-post i underkomponenten ( <contact-details>
i vårt användningsfall) kommer automatiskt att ändras till [email protected]
- förändring av förälder sprids omedelbart till barnet.
Tvåvägsbindning
Om vi vill ha tvåvägsbindning måste vi uttryckligen ange :email.sync="email"
som :email.sync="email"
istället för :email="email"
. Om vi nu ändrar värdet på prop i barnkomponenten kommer reflektionen att återspeglas också i moderkomponenten.
I en medelstor till stor app kommer det att vara mycket svårt att upptäcka förälderstatus från barntillståndet och hålla reda på särskilt när du felsöker - Var försiktig .
Det finns inget .sync-alternativ tillgängligt i Vue.js 2.0. Tvåvägsbindningen för rekvisita avskrivs i Vue.js 2.0 .
Engångsbindning
Det är också möjligt att definiera explicit engångs bindande :email.once="email
, det är mer eller mindre liknar passera en bokstavlig, eftersom eventuella förändringar i den överordnade fastighetsvärde inte fortplanta sig till barnet.
VARNING
När objekt eller array skickas som rekvisit, passas de ALLTID PÅ REFERENS , vilket betyder oberoende av vilken bindningstyp som är exakt definierad :email.sync="email"
eller :email="email"
eller :email.once="email"
, om e-post är ett objekt eller en matris i föräldern, oavsett bindningstyp, kommer alla förändringar i prop-värdet inom barnkomponenten också att påverka värdet i föräldern.
Rekvisita som Array
I filen contact-details.js
vi definierat props:['phone', 'email']
som en matris, vilket är bra om vi inte vill ha finkornig kontroll med rekvisita.
Rekvisita som objekt
Om vi vill ha mer finkornig kontroll över rekvisita, som
- om vi vill definiera vilken typ av värden som är acceptabla som rekvisit
- vad som ska vara ett standardvärde för rekvisiten
- huruvida ett värde MÅSTE (krävs) som ska skickas för rekvisiten eller är det valfritt
då måste vi använda objektnotation för att definiera rekvisita, som vi gjort i address.js
.
Om vi författar återanvändbara komponenter som kan användas av andra utvecklare i teamet också, är det en bra praxis att definiera rekvisita som objekt så att alla som använder komponenten har en klar uppfattning om vad som ska vara typen av data och om det är obligatoriskt eller valfritt.
Det kallas också rekvisitionsvalidering . Typen kan vara vilken som helst av följande inbyggda konstruktörer:
- Sträng
- siffra
- Boolean
- Array
- Objekt
- Fungera
- eller en anpassad konstruktör
Några exempel på validering av prop som tagits från 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-fodral
HTML-attribut är addresstype
addressType
, vilket innebär att de inte kan skilja mellan addresstype
och addressType
, så när vi använder camelCase prop-namn som attribut måste vi använda deras kebab-case (bindestreck) ekvivalenter:
addressType
ska skrivas som address-type
i HTML-attribut.
Dynamiska rekvisita
Precis som du kan binda data från en vy till modellen kan du också binda rekvisita med samma v-bindningsdirektiv för att överföra information från föräldrar till barnkomponenter.
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>
Resultat
hello world
Skickar rekvisita när du använder Vue JSX
Vi har en överordnad komponent: Importerar en underordnad komponent i den skickar vi rekvisita via ett attribut. Här är attributet 'src' och vi passerar 'src' också.
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} />
);
}
};
Och en barnkomponent, där vi måste skicka rekvisita. Vi måste specificera vilka rekvisita som vi passerar.
ChildComponent.js:
export default {
props: ['src'],
render(h, {props}) {
return (
<a href = {props.src} download = "myimage" >
Click this link
</a>
);
}
};