在vue中封装一个简单的命令式弹窗组件?

179 阅读2分钟
1.具体步骤

1.在.vue文件中写了一个弹窗组件,包含确定按钮,关闭按钮,title,message等,使用 pormise 异步处理确认按钮事件

2.通过 new Vue({ render: (h) => h(DynamicDialog) }) 创建了一个新的 Vue 实例,将组件例挂载到一个虚拟的元素上( const dialogInstance = new Vue({render: (h) =>h(DynamicDialog)}).$mount() )

3.通过appendChild 把组件实例塞到body中去,实现了实例挂载(document.body.appendChild(dialogInstance.$el))

4.在 Vue 插件方法install中给vue构造函数的原型上添加方法并赋值为组件实例函数里的函数执行方法|(下面代码中的show方法)

(const dynamicDialogPlugin = {install (Vue) {Vue.prototype.showDialog=dialogInstance.showDialog = dialogInstance.children[0].show}})

5.在main.js中挂载install对象(Vue.use(dynamicDialogPlugin))

6.需要的位置命令式调用调用

注意:vue插件部分官网解释 (v2.cn.vuejs.org/v2/guide/pl…

2.弹窗代码
<!-- DynamicDialog.vue -->
<template>
  <div class="command-dialog" v-if="isVisible">
    <!-- ...(略去其他代码) -->
    <div>{{ title }}</div>
    <div class="dialog-footer">
      <button @click="confirmCallback">确认</button>
      <button @click="rejectCallback">关闭</button>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      isVisible: false,
      title: '',
      message: '',
      confirmCallback: null,
      rejectCallback: null
    }
  },
  methods: {
    show ({ title, message, isVisible, confirmCallback, rejectCallback }) {
      console.log('9999show')
      this.isVisible = isVisible
      this.title = title || '提示'
      this.message = message || '这是一个命令式弹窗'
      this.isVisible = true
      this.confirmCallback = confirmCallback || null
      this.rejectCallback = rejectCallback || null

      // 返回一个 Promise,用于处理异步逻辑
      return new Promise((resolve, reject) => {
        this.confirmCallback = () => {
          if (typeof confirmCallback === 'function') {
            confirmCallback()
          }
          this.closeDialog()
          resolve() // 执行 Promise 的 resolve
        }
        this.rejectCallback = () => {
          if (typeof rejectCallback === 'function') {
            rejectCallback()
          }
          this.closeDialog()
          reject() // 执行 Promise 的 reject
        }
      })
    },
    closeDialog () {
      this.isVisible = false
    },
    // ...(略去其他代码)
  }
};
</script>

<style scoped>
/* 样式可以根据项目需求进行修改 */
.command-dialog {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 300px;
  background-color: #fff;
  border: 1px solid #ccc;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.dialog-footer {
  padding: 10px;
  text-align: right;
}

button {
  margin-left: 8px;
}
</style>
3.vue插件代码
// dynamicDialogPlugin.js
import Vue from 'vue';
import DynamicDialog from '@/components/DynamicDialog.vue';

const dialogInstance = new Vue({
  render: (h) => h(DynamicDialog)
}).$mount();

// new Vue({ render: (h) => h(DynamicDialog) }) 创建了一个新的 Vue 实例,
// 其中 DynamicDialog 是你之前创建的动态弹窗组件。
// .render 选项用于定义 Vue 实例的渲染函数,这里使用 h(DynamicDialog) 创建了动态弹窗的虚拟节点。
// $mount() 方法将实例挂载到一个虚拟的元素上,这里没有传入具体的元素,因此实例不会直接渲染到页面上。

document.body.appendChild(dialogInstance.$el);
//dialogInstance.$el 是实例的根 DOM 元素。
// 将弹窗实例挂载到 body 中:

const dynamicDialogPlugin = {
  install(Vue) {
    Vue.prototype.$showDialog = dialogInstance.$children[0].show;
  }
};
// install 方法是每个 Vue 插件都必须有的方法,它会在调用 Vue.use(dynamicDialogPlugin) 时被调用。
// 在 install 方法中,我们将动态弹窗实例的子组件(即 DynamicDialog 组件)的 show 方法赋值给了 Vue.prototype.$showDialog。
// 这样,当我们在 Vue 组件中调用 $showDialog 时,实际上是调用了动态弹窗组件的 show 方法。

export default dynamicDialogPlugin;
4.main.js处理
// main.js
import Vue from 'vue';
import App from './App.vue';
import dynamicDialogPlugin from './plugins/dynamicDialogPlugin';

Vue.config.productionTip = false;

Vue.use(dynamicDialogPlugin);

new Vue({
  render: (h) => h(App)
}).$mount('#app');
5.调用代码
<!-- YourComponent.vue -->
<script>
export default {
  methods: {
    async showDialog() {
      try {
        await this.$showDialog({
          title: '自定义标题',
          message: '自定义消息',
          confirmCallback: () => {
            // 处理确认按钮点击的逻辑
            console.log('确认按钮被点击');
          },
          rejectCallback: () => {
            // 处理关闭按钮点击的逻辑
            console.log('关闭按钮被点击');
          }
        });

        // 在这里可以处理弹窗确认后的逻辑
        console.log('弹窗已确认');
      } catch (error) {
        // 在这里可以处理弹窗关闭或拒绝的逻辑
        console.log('弹窗已关闭或拒绝');
      }
    }
  }
};
</script>

哈:(有问题可直接评论区喷,如果有那么一点点帮助麻烦点个赞鼓励,恭喜发财)