Vue.js
puntelli
Ricerca…
Osservazioni
camelCase <=> kebab-case
Quando definisci i nomi dei tuoi props
di props
, ricorda sempre che i nomi degli attributi HTML non fanno distinzione tra maiuscole e minuscole. Ciò significa che se si definisce un prop
in caso di cammello nella definizione del componente ...
Vue.component('child', {
props: ['myProp'],
...
});
... devi chiamarlo nel tuo componente HTML come mio prop.
Trasmissione dei dati da genitore a figlio con oggetti di scena
In Vue.js, ogni istanza del componente ha il proprio ambito isolato , il che significa che se un componente padre ha un componente figlio - il componente figlio ha il proprio ambito isolato e il componente padre ha il proprio ambito isolato.
Per qualsiasi app di dimensioni medio-grandi, le seguenti convenzioni sulle best practice evitano molti mal di testa durante la fase di sviluppo e successivamente la manutenzione. Una delle cose da seguire è quella di evitare di fare riferimento / mutare i dati principali direttamente dal componente figlio . Allora, come facciamo a fare riferimento ai dati principali all'interno di un componente figlio?
Qualsiasi dato genitore è richiesto in un componente figlio dovrebbe essere passato al bambino come props
di props
dal genitore.
Caso d'uso : supponiamo di avere un database utente con due tabelle users
e addresses
con i seguenti campi:
Tabella users
nome | Telefono | |
---|---|---|
John Mclane | (1) 234 5678 9012 | [email protected] |
James Bond | (44) 777 0007 0077 | [email protected] |
tabella degli addresses
bloccare | strada | città |
---|---|---|
Nakatomi Towers | Broadway | New York |
Mi6 House | Buckingham Road | Londra |
e vogliamo avere tre componenti per visualizzare le informazioni utente corrispondenti ovunque nella nostra 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:''
}
},
}
fornitura-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>
Stiamo visualizzando i dati relativi a phone
ed e email
, che sono proprietà del user-component
nei contact-details
che non hanno dati telefonici o di posta elettronica.
Trasmissione dei dati come oggetti di scena
Quindi all'interno di user-component.js
nella proprietà template , dove includiamo il componente <contact-details>
, passiamo il telefono e i dati dell'email da <user-component>
(componente padre) a <contact-details>
( componente bambino) legandosi in modo dinamico agli oggetti di scena - :phone="phone"
e :email="email
, che è uguale a v-bind:phone="phone"
e v-bind:email="email"
Puntelli - Rilegatura dinamica
Dal momento che leghiamo in modo dinamico gli oggetti di scena, qualsiasi cambiamento nel telefono o nella posta elettronica all'interno del componente principale, ovvero <user-component>
si rifletterà immediatamente nel componente figlio, ovvero <contact-details>
.
Puntelli - come letterali
Tuttavia, se avessimo passato i valori di telefono ed e -mail come valori letterali stringa come phone="(44) 777 0007 0077" email="[email protected]"
allora non rifletterebbero eventuali modifiche ai dati che si verificano nel genitore componente.
Associazione unidirezionale
Per impostazione predefinita, la direzione delle modifiche è dall'alto verso il basso, ovvero qualsiasi modifica agli oggetti puntati dinamicamente nel componente padre si propagherà al componente figlio ma qualsiasi modifica ai valori di prop in un componente figlio non si propagherà al padre.
Ad es .: se dall'interno di <contact-details>
cambiamo l'e-mail da [email protected]
a [email protected]
, i dati parent, cioè la proprietà dei dati del telefono in <user-component>
conterranno ancora un valore di [email protected]
.
Tuttavia, se cambiamo il valore dell'email da [email protected]
a [email protected]
nel componente padre ( <user-component>
componente <user-component>
nel nostro caso d'uso), allora il valore dell'email nel componente figlio ( <contact-details>
nel nostro caso d'uso) cambierà automaticamente in [email protected]
- il cambiamento in genitore viene istantaneamente propagato al bambino.
Associazione a due vie
Se vogliamo un legame a due vie, dobbiamo specificare esplicitamente l'associazione bidirezionale come :email.sync="email"
invece di :email="email"
. Ora se cambiamo il valore dell'elica nel componente figlio, la modifica si rifletterà anche nel componente principale.
In un'app di medie e grandi dimensioni, cambiare lo stato genitore dallo stato figlio sarà molto difficile da rilevare e tenere traccia soprattutto durante il debug - Sii prudente .
Non ci sarà alcuna opzione .sync disponibile in Vue.js 2.0. Il binding a due vie per gli oggetti di scena è stato deprecato in Vue.js 2.0 .
Legatura unica
E 'anche possibile definire esplicitamente una volta vincolanti come :email.once="email
, è più o meno simile al passaggio di un letterale, perché eventuali successive variazioni del valore della proprietà genitore non si propagheranno al bambino.
AVVERTIMENTO
Quando Object o Array viene passato come prop, vengono SEMPRE PASSATI DA REFERENCE , il che significa indipendentemente dal tipo di binding esplicitamente definito :email.sync="email"
o :email="email"
o :email.once="email"
, se l'e-mail è un oggetto o una matrice nel genitore, indipendentemente dal tipo di bind, qualsiasi modifica nel valore dell'elemento di prova all'interno del componente figlio influirà anche sul valore del genitore.
Puntelli come matrice
Nel file contact-details.js
abbiamo definito props:['phone', 'email']
come una matrice, che va bene se non vogliamo un controllo a grana fine con oggetti di scena.
Oggetti di scena come oggetto
Se vogliamo più controllo a grana fine su oggetti di scena, come
- se vogliamo definire quale tipo di valori sono accettabili come il prop
- quale dovrebbe essere un valore predefinito per il puntello
- se un valore DEVE (richiesto) essere passato per il prop o è opzionale
quindi abbiamo bisogno di usare la notazione degli oggetti per definire gli oggetti di scena, come abbiamo fatto in address.js
.
Se stiamo creando componenti riutilizzabili che possono essere utilizzati anche da altri sviluppatori nel team, è buona pratica definire gli oggetti di scena come oggetti in modo che chiunque usi il componente abbia un'idea chiara di quale dovrebbe essere il tipo di dati e se è obbligatorio o facoltativo.
Si riferisce anche alla convalida degli oggetti di scena . Il tipo può essere uno qualsiasi dei seguenti costruttori nativi:
- Stringa
- Numero
- booleano
- schieramento
- Oggetto
- Funzione
- o un costruttore personalizzato
Alcuni esempi di convalida di oggetti di scena presi da 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
Gli attributi HTML non fanno distinzione tra addresstype
e minuscole, il che significa che non è possibile distinguere tra tipo di addresstype
e tipo di addressType
, quindi quando si utilizzano i nomi di oggetti camelCase come attributi, è necessario utilizzare gli equivalenti di caso kebab (segno delimitato da delimitazione):
addressType
dovrebbe essere scritto come address-type
nell'attributo HTML.
Puntelli dinamici
Così come sei in grado di associare dati da una vista al modello, puoi anche legare oggetti di scena usando la stessa direttiva v-bind per passare informazioni dai componenti padre a figlio.
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>
Risultato
hello world
Passando puntelli durante l'utilizzo di Vue JSX
Abbiamo un componente principale: importando un componente figlio in esso passeremo gli oggetti di scena tramite un attributo. Qui l'attributo è 'src' e stiamo passando anche '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} />
);
}
};
E un componente figlio, dove abbiamo bisogno di passare oggetti di scena. Dobbiamo specificare quali oggetti stiamo passando.
ChildComponent.js:
export default {
props: ['src'],
render(h, {props}) {
return (
<a href = {props.src} download = "myimage" >
Click this link
</a>
);
}
};