我有一个全局确认模态组件注册在我的默认布局文件中,然后我会尝试从我的pages/index.vue访问它,但调用this.$refs只会返回一个空对象。将模态组件放在我的pages/index.vue中是可行的,但它会破坏我的全局确认模态的目的。
布局/默认.vue
<template lang="pug">
v-app(v-if="show")
v-main
transition
nuxt
confirm(ref='confirm')
</template>
<script>
import confirm from '~/components/confirm.vue'
export default {
components: { confirm },
data: () => ({
show: false
}),
async created() {
const isAuth = await this.$store.dispatch("checkAuth")
if (!isAuth) return this.$router.push("/login")
this.show = true
}
}
</script>
组件/确认值
<template>
<v-dialog v-model="dialog" :max-width="options.width" @keydown.esc="cancel">
<v-card>
<v-toolbar dark :color="options.color" dense flat>
<v-toolbar-title class="white--text">{{ title }}</v-toolbar-title>
</v-toolbar>
<v-card-text v-show="!!message">{{ message }}</v-card-text>
<v-card-actions class="pt-0">
<v-spacer></v-spacer>
<v-btn color="primary darken-1" @click.native="agree">Yes</v-btn>
<v-btn color="grey" @click.native="cancel">Cancel</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
data: () => ({
dialog: false,
resolve: null,
reject: null,
message: null,
title: null,
options: {
color: 'primary',
width: 290
}
}),
methods: {
open(title, message, options) {
this.dialog = true
this.title = title
this.message = message
this.options = Object.assign(this.options, options)
return new Promise((resolve, reject) => {
this.resolve = resolve
this.reject = reject
})
},
agree() {
this.resolve(true)
this.dialog = false
},
cancel() {
this.resolve(false)
this.dialog = false
}
}
}
</script>
然后我想从我的页面/index.vue调用它,就像这样(如果ref在这里,它会工作,但我想一个全局确认模态)
methods: {
async openConfirm() {
console.log("openConfirm")
if (await this.$refs.confirm.open('Delete', 'Are you sure?', { color: 'red' })) {
console.log('--yes')
}else{
console.log('--no')
}
},
2条答案
按热度按时间mbzjlibv1#
简短的回答是:不要这样滥用$ref,最终,它只会导致反模式被反模式所包裹。
与您要完成的确切任务相关的更详细的答案:我现在已经在一些Vue项目上处理了这个完全相同的事情(全局的,基于承诺的确认对话框),这是到目前为止工作得非常好的:
1.将确认对话框设置为它自己的独立“模块”,这样您就可以使用两行将其添加到main.js中:
(side要点:还有其他一些“全局模块化组件”,如警报等...)
1.使用JS文件可以编排设置流程、承诺管理和组件示例化。例如:
1.将其挂载到Vue.prototype,这样您就可以在应用的任何组件中使用它,只需调用:
this.$confirm(...)
1.当你构建你的Vue组件(confirm-dialog.vue)时,你只需要单向绑定标题、文本和选项的属性,单向绑定对话框的dlg属性,或者通过getter和setter的计算属性设置一个双向绑定......无论哪种方式......
1.如果用户确认,则使用
true
发出“confirmed”事件。因此,从confirm-dialog.vue组件:this.$emit('confirmed', true);
1.如果他们关闭对话框,或者点击“否”,那么就会发出false,这样承诺就不会一直存在:
this.$emit('confirmed', false);
1.现在,您可以从任何组件中使用它,如下所示:
nxowjjhe2#
在nuxt项目的默认布局中,放置组件,例如
Confirm
,如下所示:然后可以使用组件的
open
方法,如下所示:棘手的事情是如何找到包含在布局中的组件。
$root.$children[2]
部分似乎在开发阶段工作,但一旦部署,它必须是$root.$children[1]
。所以我最后做了下面的事情:
背景:我的项目正在生产中,但是在以特定模式进行任何保存之前,我提出了一个新的要求,即在保存之前获得确认。我可以使用单向
event bus
,但是要做到这一点,确认之后的其余代码必须重构,以便在每个保存位置作为回调传递。**[31 Oct 22]**同时,项目迁移到组合API,最后使用
store
的getter/setter共享Confirm
组件的ref,以避免使用上述查找ref的黑客方法: