Après quelques recherches, la suggestion suivante de M. Evan You a été trouvée: https://github.com/vuejs/vue/issues/7349#issuecomment- 354937350
Donc, sans aucune hésitation, je l'ai essayé:
Modèle de composant
DataModel: { mainSectionA: { sections: { sectionA: { sections: { elementA: { values: { ... } }, elementB: { values: { ... } } } values: { ... } } sectionB: { elementA: { values: { ... } }, elementB: { values: { ... } } } }, values: { ... } }, mainSectionB: { sections: { elementA: { values: { ... } }, elementB: { values: { ... } }, elementC: { values: { ... } }, ... elements }, values: { ... } } }
JS Logic
[Vue warn]: Invalid handler for event "click": got null
Mais pour le cas décrit, il en résulte une erreur lors du rendu:
<script> export default { name: `product-section`, props: [`section`, `sectionName`, `depth`], methods: { toggleSectionElements() { ... magic } }, computed: { dataType() { if (this.$props.section.sections || this.$props.depth === 0) { return `section` } else { return `element` } } } } </script>
Quelqu'un peut-il s'il vous plaît suggérer ce qui a été mal fait? : réflexion:
Mettre à jour
À quoi ressemble le Modèle de données
:
<template> <div v-on='{ click: dataType === `section` ? toggleSectionElements : null }'> ... magic </div> <template>
3 Réponses :
ici:
click: dataType === `section` ? toggleSectionElements : ()=>{}
dans le cas différent, vous passez null, mais la valeur au clic attend une fonction. vous pouvez essayer une fonction emptry:
click: dataType === `section` ? toggleSectionElements : null
Le fait de devoir utiliser des éléments aussi originaux montre l'absence de fonctionnalité dans Vue.
Modifiez-le simplement comme suit et cela fonctionnera
v-on="condition ? { mouseover } : {}"
ou, si votre gestionnaire s'appelle mouseover
v-on="condition ? { mouseover: handler } : {}"
Au lieu de polluer votre modèle avec une logique ternaire, vous devriez plutôt effectuer la vérification à l'intérieur du gestionnaire de clics. Cela rend non seulement votre modèle plus lisible, mais facilite également la maintenance du code puisque toute la logique a été abstraite et déléguée au rappel du gestionnaire d'événements.
Par conséquent, la solution rapide consiste en fait à assurez-vous que toggleSectionElements ()
ne fonctionnera que lorsqu'un dataType
correct est présent. Ceci peut être réalisé en utilisant une clause de garde:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <my-collection /> </div> <script type="text/x-template" id="my-collection-component"> <div> <component v-for="(item, i) in collection" v-bind:key="i" v-bind:is="componentToUse(item.dataType)" v-bind:itemData="item" /> </div> </script> <script type="text/x-template" id="my-section-component"> <div @click="toggle" class="box"> <h1>{{ itemData.dataType }}</h1> <p>{{ itemData.description }}</p> <p>Clicking on me will invoke a section-specific logic</p> </div> </script> <script type="text/x-template" id="my-element-component"> <div class="box"> <h1>{{ itemData.dataType }}</h1> <p>{{ itemData.description }}</p> <p>Clicking on me will do nothing</p> </div> </script>
Encore mieux, c'est que si des gestionnaires séparés doivent être attribués à chaque dataType
: vous pouvez alors créer une fonction d'usine à cet effet:
.box { border: 1px solid #999; cursor: pointer; margin: 10px; padding: 10px; } .box:hover { background-color: #eee; }
Puisqu'il peut être coûteux de lier des gestionnaires d'événements de clic à des éléments qui finissent par ne rien faire, vous pouvez également décomposer votre composant pour qu'il soit plus atomique. L'élément de collection sera responsable de recevoir un tableau de "section" ou "élément", et chaque "section" / "élément" aura son propre composant, quelque chose comme ceci:
, qui contient tous les composants "section" et "élément"
C'est là que VueJS devient vraiment puissant: vous pouvez utiliser composant dynamique dans
pour déterminer quel composant utiliser en fonction du dataType
rencontré.
Cela se fait en exécutant un v-for
à travers la collection, puis en utilisant v-bind: is = "..."
pour déterminer si un élément de collection spécifique doit utiliser "section" ou "élément". Je comprends que cela va probablement sortir du cadre de votre question initiale, mais c'est une conception intéressante à prendre en compte:
const collectionComponent = Vue.component('my-collection', { template: '#my-collection-component', data: function() { return { collection: [{ dataType: 'section', description: 'Hello I am section 1' }, { dataType: 'element', description: 'Hello I am element 1' }, { dataType: 'section', description: 'Hello I am section 2' }, { dataType: 'element', description: 'Hello I am element 2' }] } }, methods: { componentToUse(dataType) { return 'my-' + dataType; } } }); const sectionComponent = Vue.component('my-section', { template: '#my-section-component', props: ['itemData'], methods: { toggle() { console.log('Doing some magic.'); } } }); const elementComponent = Vue.component('my-element', { template: '#my-element-component', props: ['itemData'] }); new Vue({ el: '#app' });
methods: { // This is just a factory function toggleElements() { switch (this.dataType()) { case 'section': return this.toggleSectionElements; case 'element': // Something else... } }, toggleSectionElements() { // Magic for section element } }
toggleSectionElements() { // Guard clause to prevent further code execution if (this.dataType() !== 'section') return; // Magic here }
Merci pour votre suggestion, Terry. Je pensais à votre suggestion comme approche initiale. Je n'ai pas posté ici mais ce modèle est une sorte de composant récursif. Où à la fin, il finit par rendre environ 10 sections et 60 éléments.
Les sections devraient avoir l'auditeur, contrairement aux éléments, trouvez-vous raisonnable de vérifier réellement dans l'auditeur, plutôt que de ne pas tout ajouter? (en fait des curiosités)
@volna C'est une préoccupation appropriée. Une meilleure solution est d'avoir en fait des composants atomiques : dans ce cas, vous aurez deux composants séparés: un à consommer par "section" et un autre à consommer par "élément". Le composant "section" peut avoir l'événement click lié à celui-ci, alors que "l'élément" n'est pas obligé de le faire.