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 e-mail
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>
        );
    }
};


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow