Vue.js associa le proprietà dell’object

Perché non posso associare le proprietà dell’object in Vue? L’object addr non reagisce immediatamente, ma il test è reattivo, come mai? In questo caso, come dovrei legarlo?

HTML

 

{{addr}}
{{addr.contactNum}}
{{test}}

Javascript

 var vm = new Vue({ el: '#app', data: { addr: {}, test: "" } }); 

Jsfiddle

Durante l’inizializzazione, Vue imposta getter e setter per ogni proprietà nota. Poiché contactNum non è inizialmente impostato, Vue non è a conoscenza di tale proprietà e non può aggiornarlo correttamente. Questo può essere facilmente risolto aggiungendo contactNum al tuo object addr .

 var vm = new Vue({ el: '#app', data: { addr: { contactNum: "" // <-- this one }, test: "" } }); 

Quanto sopra è chiamato reattività in Vue. Poiché Vue non supporta l'aggiunta di proprietà dynamicmente al suo sistema di reattività, potremmo aver bisogno di un qualche tipo di soluzione alternativa. Una ansible soluzione è fornita dall'API. In caso di proprietà aggiunte dynamicmente possiamo usare Vue.set(vm.someObject, 'b', 2) .

In questo modo il markup dovrebbe essere aggiornato. Invece di usare v-model , sarebbe meglio usare un listener di eventi come @input . In questo caso il nostro markup potrebbe assomigliare a questo.

  

Quindi in pratica la funzione viene triggersta ogni volta che cambia il valore degli elementi di input. Ovviamente fare ciò richiederà anche alcune modifiche alla parte JS.

 var vm = new Vue({ el: '#app', data: { addr: {}, test: "" }, methods: { update: function(obj, prop, event) { Vue.set(obj, prop, event.target.value); } } }); 

Poiché Vue triggers Vue.set() su qualsiasi elemento reattivo, lo chiamiamo semplicemente perché Vue non riconosce una proprietà aggiunta dynamicmente come una retriggers. Naturalmente, questa è solo una soluzione ansible e potrebbero esserci molti altri accorgimenti. Un esempio pienamente funzionante può essere visto qui .

Come per i miei commenti, ci sono molte cose che vuoi considerare:

  • Il motivo per cui il tuo codice non funziona è dovuto all’incapacità intrinseca di JS di controllare i cambiamenti nelle proprietà dell’object . Ciò significa che anche se addr è reattivo, qualsiasi proprietà aggiunta ad addr che non viene eseguita quando viene dichiarata la renderà non retriggers. Fare riferimento ai documenti VueJS per maggiori dettagli: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
  • Se si dispone di un numero arbitrario di campi di input, è probabilmente meglio comporre un componente di input personalizzato e utilizzare semplicemente v-for per iniettare iterativamente i campi di input in base al numero di campi di input che si hanno.

Ora torniamo al secondo punto, se sai quali campi avrà l’ addr , puoi semplicemente dichiararlo nella tua app. Creiamo un nuovo metodo updateFormData , che viene chiamato dal componente:

 data: { addrFields: ['contactNum', ...], addr: {}, test: "" }, methods: { updateFormData: function(id, value) { this.$set(this.addr, id, value); } } 

Possiamo ancora archiviare i dati del modulo nell’object addr , che verrà aggiornato dal metodo updateFormData basato sul payload ricevuto utilizzando .$set() . Ora possiamo creare un componente Vue personalizzato per il tuo elemento di input.

Nell’esempio seguente, il componente eseguirà iterazioni su tutti i tuoi addrFields e passerà l’ addrField come prop utilizzando :id="addrField" . Vogliamo anche assicurarci di acquisire l’evento updated nome personalizzato emesso dal componente.

  

Il modello può avere un aspetto simile al seguente. Usa semplicemente l’ id prop per il suo id , name e attributo placeholder (quest’ultimo per una facile identificazione nella demo). @input eventi @change e @input , forzandoli ad triggersre il callback updated :

  

Nella logica del componente, si fa sapere che riceverà id come supporto e che dovrebbe emettere un evento inputUpdated usando $.emit() . Alleghiamo l’ID e il valore come payload, in modo che possiamo informare il genitore cosa è stato aggiornato:

 var myInput = Vue.component('my-input', { template: '#my-input', props: { id: { type: String } }, methods: { updated: function() { this.$emit('inputUpdated', this.id, this.$el.value); } } }); 

Con il codice sopra, abbiamo un esempio funzionante. In questo caso, ho creato un array arbitrario di campi di input: contactNum , a , b e c :

 var myInput = Vue.component('my-input', { template: '#my-input', props: { id: { type: String } }, methods: { updated: function() { this.$emit('updated', this.id, this.$el.value); } } }); var vm = new Vue({ el: '#app', data: { addrFields: ['contactNum', 'a', 'b', 'c'], addr: {}, test: "" }, methods: { updateFormData: function(id, value) { this.$set(this.addr, id, value); } } }); 
  

addr: {{addr}}
addr.contactNum: {{addr.contactNum}}
test: {{test}}

Modifica i tuoi data Vue con questo dato che i metodi getter e setter non sono impostati. Inoltre, controlla il rendering reattivo dichiarativo sui documenti Vue qui :

 data: { addr: { contactNum: "" // <-- this one }, test: "" }