Откройте диалог Vuetify из шаблона компонента в VueJS
Я использую VueJS Vuetify framework, и мне нужно открыть диалог - который импортируется как шаблон компонента - из другого шаблона. После нажатия кнопки "Меню" в приложении " App.vue" Модаль должен открыть. Вот моя настройка:
- App.vue = шаблон навигации с кнопкой меню
- Modal.vue = Модальный шаблон, импортированный как глобальный в main.js
main.js
import Modal from './components/Modal.vue'
Vue.component('modal', Modal)
Шаблон Modal.vue:
<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 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>
Как открыть диалог?
Ответы
Ответ 1
Вы можете открыть диалоговое окно с помощью пользовательских событий и использовать шину событий для связи с не родительским и дочерним.
Если ваше приложение становится немного сложнее, я рекомендую вам использовать Vuex для управления состоянием.
Решение для шины событий:
В вашем main.js или в новом файле создайте и экспортируйте новый экземпляр Vue:
export const bus = new Vue()
В app.vue импортируйте bus
и испустите событие:
<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>
В modal.vue также импортируйте шину и прослушайте событие в созданном hook:
<script>
import {bus} from '../main'
export default {
created () {
var vm = this
bus.$on('dialog', function (value) {
vm.dialog = value
})
}
}
</script>
Ответ 2
Шина событий не требуется и V-модель
Обновить:
Когда я впервые ответил на это, я опубликовал свой ответ как "обходной путь", так как в то время он не казался полностью "правильным", и я был новичком в Vue.js. Я хотел открыть или закрыть диалог, используя директиву v-модели, но я не смог туда добраться. Через некоторое время я нашел, как это сделать в документации, используя событие ввода и свойство value, и вот как я думаю, что это должно быть сделано без шины событий.
Родительский компонент:
<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>
Дочерний компонент (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>
Оригинальный ответ:
Я смог обойти это без необходимости в шине глобального события.
Я использовал вычисляемое свойство с геттером и сеттером. Так как Vue предупреждает вас об изменении свойства родителя напрямую, в установщике я просто отправил событие родителю.
Вот код:
Родительский компонент:
<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>
Дочерний компонент (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>
Ответ 3
Существует много способов сделать это: Vuex, Event Bus, реквизиты, с которыми вы можете управлять, должны ли модальные функции открывать или закрывать. Я покажу вам свой любимый способ с использованием модификатора .sync
:
Сначала я упрощу вам вопрос (часть кода)
Родительский компонент
<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>
Детский (диалоговый) компонент
<template>
<v-layout row justify-center>
<v-dialog v-model="dialog" persistent max-width="290">
<v-card>
<v-card-title class="headline">Use Google 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>
Ответ 4
Самый простой способ, который я нашел, это:
в data() компонента, возвратите атрибут, скажем, диалог.
Когда вы включаете компонент, вы можете установить ссылку на свой тег компонента. Например:
import Edit from '../payment/edit.vue';
<edit ref="edit_reference"></edit>
Затем, внутри моего компонента, я установил метод:
open: function () {
var vm = this;
vm.dialog = true;
}
Наконец, я могу назвать это от родителя, используя:
editar(item)
{
var vm = this;
vm.$refs.edit_reference.open();
}
Ответ 5
в template
App.vue
добавьте это
<modal></model>
он отобразит ваш текущий шаблон Modal.vue
с v-btn
и v-dialog
теперь внутри него будет одна button
- Open Dialog
когда вы нажмете на этот модальный файл.
Ответ 6
Простой минимальный рабочий пример
codepen
Передайте value
prop в качестве value
в v-dialog
и генерируйте input
событие всякий раз, когда вы хотите закрыть его:
//CustomDialog.vue
<v-dialog :value="value" @input="$emit('input')">
<v-btn color="red" @click.native="$emit('input')">Close</v-btn>
</v-dialog>
...
props:['value']
и добавить V-модель к родителю
//Parent.vue
<custom-dialog v-model="dialog">
Так что нет никакой пользовательской шины событий, нет data
, нет watch
, нет computed
.