J'utilise le VueJS cadre Vuetify et je dois ouvrir une boîte de dialogue - importée en tant que modèle de composant - à partir d'un autre modèle. Une fois le bouton Menu dans App.vue eu cliqué, le modal devrait s'ouvrir. Voici ma configuration:
main.js
import Modal from './components/Modal.vue'
Vue.component('modal', Modal)
Modal.vue Template:
<template>
<v-layout row justify-center>
<v-btn color="primary" dark @click.native.stop="dialog = true">Open Dialog</v-btn>
<v-dialog v-model="dialog" max-width="290">
<v-card>
<v-card-title class="headline">Use Google's location service?</v-card-title>
<v-card-text>Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green darken-1" flat="flat" @click.native="dialog = false">Disagree</v-btn>
<v-btn color="green darken-1" flat="flat" @click.native="dialog = false">Agree</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
export default {
data () {
return {
dialog: false
}
}
}
</script>
Comment ouvrir le dialogue?
Vous pouvez ouvrir la boîte de dialogue à l'aide d'événements personnalisés et à l'aide d'un bus d'événements pour les communications non parent-enfant .
Si votre application devient un peu plus complexe, je vous recommande d'utiliser Vuex pour la gestion d'état .
Solution de bus d'événements:
Dans votre main.js ou dans un nouveau fichier, créez et exportez une nouvelle instance Vue:
export const bus = new Vue()
Dans app.vue , importez le bus
et émettez l'événement:
<template>
<div>
<button @click.prevent="openMyDialog()">my button</button>
</div>
</template>
<script>
import {bus} from '../main' // import the bus from main.js or new file
export default {
methods: {
openMyDialog () {
bus.$emit('dialog', true) // emit the event to the bus
}
}
}
</script>
Dans modal.vue importez également le bus et écoutez l'événement dans le hook créé:
<script>
import {bus} from '../main'
export default {
created () {
var vm = this
bus.$on('dialog', function (value) {
vm.dialog = value
})
}
}
</script>
Quand j'ai d'abord répondu à cela, j'ai posté ma réponse en tant que "solution de contournement", car elle ne me semblait pas complètement "correcte" à l'époque et que j'étais nouveau dans Vue.js. Je voulais ouvrir ou fermer le dialogue en utilisant une directive v-model , mais je n'y suis pas parvenu. Après un certain temps, j'ai trouvé comment faire cela dans la documentation , en utilisant l'événement d'entrée et le value value , et voici comment je pense que cela devrait être fait sans bus d'événements.
Composant parent:
<template>
<v-btn color="accent" large @click.stop="showScheduleForm=true">
<ScheduleForm v-model="showScheduleForm" />
</template>
<script>
import ScheduleForm from '~/components/ScheduleForm'
export default {
data () {
return {
showScheduleForm: false
}
},
components: {
ScheduleForm
}
}
</script>
Composant enfant (ScheduleForm):
<template>
<v-dialog v-model="show" max-width="500px">
<v-card>
<v-card-actions>
<v-btn color="primary" flat @click.stop="show=false">Close</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
props: {
value: Boolean
},
computed: {
show: {
get () {
return this.value
},
set (value) {
this.$emit('input', value)
}
}
}
}
</script>
J'ai pu contourner ce problème sans avoir besoin d'un bus d'événements mondial.
J'ai utilisé une propriété calculée avec un getter ET un setter. Depuis Vue vous avertit de la mutation directe de la propriété parent, dans l'émetteur, j'ai simplement émis un événement au parent.
Voici le code:
Composant parent:
<template>
<v-btn color="accent" large @click.stop="showScheduleForm=true">
<ScheduleForm :visible="showScheduleForm" @close="showScheduleForm=false" />
</template>
<script>
import ScheduleForm from '~/components/ScheduleForm'
export default {
data () {
return {
showScheduleForm: false
}
},
components: {
ScheduleForm
}
}
</script>
Composant enfant (ScheduleForm):
<template>
<v-dialog v-model="show" max-width="500px">
<v-card>
<v-card-actions>
<v-btn color="primary" flat @click.stop="show=false">Close</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
props: ['visible'],
computed: {
show: {
get () {
return this.visible
},
set (value) {
if (!value) {
this.$emit('close')
}
}
}
}
}
</script>
Il y a plusieurs façons de le faire, telles que Vuex, Event Bus, Props avec lequel vous pouvez gérer si le modal doit s'ouvrir ou se fermer. Je vais vous montrer mon moyen préféré en utilisant le modificateur
.sync
:
Je vais d'abord vous simplifier la question (la partie code)
composant parent
<template>
<div>
<button @click="dialog=true">Open Dialog</button>
<Child :dialog.sync="dialog" />
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data: {
return {
dialog: false
}
}
}
</script>
composant enfant (dialogue)
<template>
<v-layout row justify-center>
<v-dialog v-model="dialog" persistent max-width="290">
<v-card>
<v-card-title class="headline">Use Google's location service?</v-card-title>
<v-card-text>Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green darken-1" flat @click.native="close">Close</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
export default {
props: {
dialog: {
default: false
}
},
methods: {
close() {
this.$emit('update:dialog', false)
}
}
}
</script>
Passez value
prop comme value
à v-dialog
composant et à partir de la boîte de dialogue enfant, émettez un événement input
à chaque fois que vous souhaitez le fermer:
//CustomDialog.vue
<v-dialog :value="value" @input="$emit('input')">
<v-btn color="red" @click.native="$emit('input')">Close</v-btn>
</v-dialog>
...
props:['value']
et ajoutez v-model à votre parent
//Parent.vue
<custom-dialog v-model="dialog">
Donc, pas de bus d'événements personnalisé, pas de data
, ni de watch
, ni de computed
.
La façon la plus simple que j'ai trouvée de le faire est:
dans data () du composant, retourne un attribut, disons dialogue.
Lorsque vous incluez un composant, vous pouvez définir une référence à votre balise de composant. Par exemple.:
import Edit from '../payment/edit.vue';
<edit ref="edit_reference"></edit>
Ensuite, dans ma composante, j'ai défini une méthode:
open: function () {
var vm = this;
vm.dialog = true;
}
Enfin, je peux l'appeler de parent en utilisant:
editar(item)
{
var vm = this;
vm.$refs.edit_reference.open();
}
dans votre App.vue
template
ajoutez ceci
<modal></model>
il rendra votre modèle actuel Modal.vue
avec v-btn
et v-dialog
maintenant, à l'intérieur, il y aura un button
- Open Dialog
lorsque vous cliquerez sur ce modal qui s'ouvrira.