![](/img/trans.png)
[英]Vuejs & Vuetify - Using Tinymce as a component in a dialog requires reloading
[英]Open a Vuetify dialog from a component template in VueJS
我正在使用 VueJS Vuetify 框架,我需要從另一個模板打開一個對話框 - 作為組件模板導入。 一旦App.vue中的Menu按鈕被點擊,Modal 應該會打開。 這是我的設置:
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'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>
如何打開對話框?
當我第一次回答這個問題時,我將我的答案發布為“解決方法”,因為當時感覺它並不完全“正確”,而且我是 Vue.js 的新手。 我想使用v-model指令打開或關閉對話框,但我無法到達那里。 一段時間后,我在文檔中找到了如何使用input 事件和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>
我能夠在不需要全局事件總線的情況下解決這個問題。
我使用了一個帶有 getter 和 setter 的計算屬性。 由於 Vue 會警告您直接更改父屬性,因此在設置器中我只是向父級發出了一個事件。
這是代碼:
父組件:
<template>
<v-btn color="accent" large @click.stop="showScheduleForm=true"></v-btn>
<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>
有很多方法可以做到這一點,例如 Vuex、Event Bus、Props,您可以使用它們來管理模式是否必須打開或關閉。我將向您展示我最喜歡的使用
.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'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>
將value
prop 作為value
傳遞給v-dialog
組件,並在您想要關閉它時從子對話框發出input
事件:
//CustomDialog.vue
<v-dialog :value="value" @input="$emit('input', $event)">
<v-btn color="red" @click.native="$emit('input', false)">Close</v-btn>
</v-dialog>
...
props:['value']
並將 v-model 添加到您的父級
//Parent.vue
<custom-dialog v-model="dialog">
所以沒有自定義事件總線,沒有data
,沒有watch
,沒有computed
。
您可以使用自定義事件打開對話框,並使用事件總線進行非父子通信。
如果您的應用程序變得有點復雜,我建議您使用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 中還導入總線並在 created 鈎子中監聽事件:
<script>
import {bus} from '../main'
export default {
created () {
var vm = this
bus.$on('dialog', function (value) {
vm.dialog = value
})
}
}
</script>
我發現最簡單的方法是:
在組件的 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();
}
我更喜歡使用這個:
DialogConfirm.vue
<template>
<v-dialog :value="visible" max-width="450">
<v-card>
<v-card-title v-text="title" />
<v-card-text v-text="message" />
<v-card-actions v-if="visible">
<template v-for="action in value">
<v-spacer :key="action.label" v-if="typeof action == 'string'" />
<v-btn
v-else
text
:key="action.label"
v-text="action.label"
@click="doAction(action.action)"
:color="action.color"
/>
</template>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component';
import { Prop, Watch } from 'vue-property-decorator';
@Component
export default class DialogConfirm extends Vue {
@Prop({ type: String, default: "Confirm" })
title: string
@Prop({ type: String, default: "Are you sure?" })
message: string
@Prop({ type: Array, default: undefined })
value: { label: string, action: () => boolean, color: string }[]
get visible() {
return Array.isArray(this.value) && this.value.length > 0
}
doAction(action: () => boolean) {
if ('undefined' == typeof action || action() !== false) {
this.$emit('input', null)
}
}
}
</script>
使用示例
/** Disable AP Mode */
setApMode(enable: boolean) {
const action = () => {
Api.get('wifi', {
params: {
ap: enable
}
}).then(response => this.$store.dispatch('status'))
}
if (enable == true) {
// No confirmation
return action();
}
this.dialogTitle = 'Are you sure?'
this.dialogMessage = "you may lost connection to this device.";
this.dialogActions = [
{
label: 'Cancel',
color: 'success'
},
'spacer',
{
label: "OK, Disable it",
color: "error",
action
}
]
}
在你的App.vue
template
中添加這個
<modal></model>
它將使用v-btn
和v-dialog
呈現您當前的Modal.vue
模板
現在里面會有一個button
- 當您單擊該模式時Open Dialog
將打開。
methods: {
openDialog(e) {
this.dialog = true;
}
},
這個對我有用
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.