Vue.js如何动态创建组件并实现可调用返回结果的全局弹窗插件
现有代码核心问题
- 变量引用错误:
global.js中导入组件名为PopUpComponent,但调用Vue.extend时误用了未定义的CirrusPopUpComponent变量 - 配置笔误:
PopUpComponent.vue中icon_color属性默认值写为无效值while,正确应为white fire方法未实现参数接收和Promise返回,无法满足链式调用then的需求- 组件实例挂载后未插入到页面DOM树中,弹窗不会被渲染显示
- 调用
fire时传入的动态配置没有覆盖组件props的初始值 - 没有监听组件的
input事件,用户操作结果无法传递到调用层 - 未注入Vuetify实例,使用
v-dialog组件会出现样式/功能异常
修复方案
1. 修改PopUpComponent.vue
<template> <div> <v-dialog v-model="dialog_confirmation" max-width="400" content-class="c8-page"> <v-card> <v-card-title class="headline"> <v-icon v-show="icon_show" :color="icon_color">{{ icon }}</v-icon> {{ title }} <a href="#" class="dialog-close" @click.prevent="dialog_confirmation = false"><v-icon>mdi-close</v-icon></a> </v-card-title> <v-card-text> <div style="margin:10px;" v-html="message"></div> </v-card-text> <v-card-actions> <v-spacer /> <v-btn color="primary" depressed tile small @click="updateValue(1)">Yes</v-btn> <v-btn color="primary" depressed tile small @click="updateValue(2)">No</v-btn> </v-card-actions> </v-card> </v-dialog> </div> </template> <script> export default { name: 'Cirrus-Alert-Confirmation', props: { title: {default: ''}, message: {default: ''}, icon_color: {default: 'white'}, icon: {default: 'warning'}, icon_show: {default: false} }, data() { return { dialog_confirmation: false } }, methods: { fire: function(options = {}) { // 合并传入的配置参数 Object.keys(options).forEach(key => { if (this.$props.hasOwnProperty(key)) { this[key] = options[key] } }) this.dialog_confirmation = true // 返回Promise支持链式调用 return new Promise(resolve => { // 监听按钮点击事件 this.$once('input', value => { resolve({ value }) this.$nextTick(() => this.$destroy()) }) // 监听关闭按钮点击事件 this.$watch('dialog_confirmation', newVal => { if (!newVal) { resolve({ value: 0 }) this.$nextTick(() => this.$destroy()) } }, { once: true }) }) }, updateValue: function(value) { this.$emit('input', value); this.dialog_confirmation = false; } } } </script>
2. 修改global.js
import Vue from 'vue' import PopUpComponent from "../components/elements/PopUpComponent"; Vue.prototype.$filters = Vue.options.filters; const AlertConstructor = Vue.extend(PopUpComponent) // 封装全局调用方法,无需提前初始化 Vue.prototype.$alert = { fire(options = {}) { const instance = new AlertConstructor({ vuetify: window.vuetify, // 注入Vuetify实例避免组件异常 propsData: options }) // 挂载组件并插入到页面DOM instance.$mount() document.body.appendChild(instance.$el) return instance.fire(options) } }
3. 调整main.js注入Vuetify实例
import '../../plugins/global'; import Vue from 'vue' import SuiVue from 'semantic-ui-vue' import vuetify from '你的vuetify配置文件路径' import store from '你的vuex配置文件路径' import FormTemplate from '../../components/modules/Templates/FormTemplate.vue'; // 全局挂载Vuetify实例供弹窗组件调用 window.vuetify = vuetify new Vue({ el: '#app', SuiVue, vuetify, store, components : { 'main-template-component' : FormTemplate, } }).$mount('#app')
4. 调用方式(完全符合预期)
任意Vue组件中无需提前初始化,直接调用即可:
this.$alert.fire({ title: 'Confirmation message'}) .then((result) => { if(result.value == 1) console.log("option 1 is pressed") if(result.value == 2) console.log("option 2 is pressed") if(result.value == 0) console.log("user closed the popup") });
内容的提问来源于stack exchange,提问作者Daniel Javier
相关产品推荐
相关产品推荐

