Vue3 如何优雅的使用 createApp 自定义通用Dialog

这篇具有很好参考价值的文章主要介绍了Vue3 如何优雅的使用 createApp 自定义通用Dialog。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近在做一个项目的技术栈升级,从Vue2升级至Vue3,Vue2中有一个通用的全局 Dialog 方法,是通过 Vue.extend 来实现的,具体请看下方的Vue2代码:

一、main.js 中定义通用方法
Vue.prototype.$dialog = {
    open(component, args) {
        return new Promise((resolve, reject) => {
            let Dialog = Vue.extend(component);
            var $vm = new Dialog({
                el: document.createElement("div"),
                router,
                store,
                eventBus: new Vue(),
            });
            var node = document.body.appendChild($vm.$el);

            $vm.open(args).then(
                result => {
                    if (resolve) {
                        resolve(result);
                    }
                    node.remove();
                    $vm.$destroy();
                },
                (arg) => {
                    if (reject) {
                        reject(arg)
                    }
                    node.remove();
                    $vm.$destroy();
                }
            );
        });
    }
};
二、定义通用 DialogLayout.vue
<template>
  <el-dialog :title="title" :visible.sync="visible" :center="center" :modal="true" :width="width"
    class="n-dialog-layout" :class="$slots.footer ? 'has-footer' : ''" :modal-append-to-body="true"
    :append-to-body="true" :lock-scroll="true" :show-close="showClose" :close-on-click-modal="false"
    :before-close="beforeClose" @opened="$emit('opened')" @close="handleClose" :fullscreen="fullscreen">
    <slot name="title" slot="title"></slot>
    <slot></slot>
    <slot name="footer" slot="footer"></slot>
  </el-dialog>
</template>
<script>
export default {
  name: "n-dialog-layout",
  props: {
    title: {},
    fullscreen: {
      default: false,
      type: Boolean,
    },
    width: {
      default: "50%",
      type: String,
    },
    showClose: {
      default: true,
      type: Boolean,
    },
    center: {
      default: false,
      type: Boolean,
    },
    beforeClose: {
      default: (done) => {
        done();
      },
      type: Function,
    },
  },
  data() {
    return {
      promise: null,
      resolve: null,
      reject: null,
      visible: false,
      confirmClose: false,
      result: {},
    };
  },
  methods: {
    open() {
      this.confirmClose = false;
      this.promise = new Promise((resolve, reject) => {
        this.resolve = resolve;
        this.reject = reject;
        this.visible = true;
      });
      return this.promise;
    },
    close(result) {
      this.confirmClose = true;
      this.result = result;
      this.visible = false;
    },
    cancel(arg) {
      this.confirmClose = false;
      this.result = arg;
      this.visible = false;
    },
    handleClose() {
      if (this.confirmClose) {
        this.resolve(this.result);
      } else {
        this.reject(this.result);
      }
    },
  },
};
</script>
三、 定义需要通过 Dialog 打开的具体页面
<template>
  <n-dialog-layout :title='l("ChangePassword")' ref="dialog">
    <div class="info" v-loading="loading">
      <el-form ref="passwordForm" status-icon size="large" :model="item" label-width="100px" label-position="top"
        class="m-b" :rules="rules">
        <el-form-item :label="l('CurrentPassword')" prop="currentPassword">
          <el-input type="password" v-model="item.currentPassword"></el-input>
        </el-form-item>
        <el-form-item :label="l('NewPassword')" prop="password">
          <el-input type="password" v-model="item.password"></el-input>
        </el-form-item>
        <el-form-item :label="l('NewPasswordRepeat')" prop="confirmPassword">
          <el-input type="password" v-model="item.confirmPassword"></el-input>
        </el-form-item>
      </el-form>
    </div>
    <template slot="footer">
      <span class="dialog-footer">
        <el-button @click="cancel()" size="large">{{ l('Cancel') }}</el-button>
        <el-button type="primary" @click="ok()" size="large">{{ l('Save') }}</el-button>
      </span>
    </template>
  </n-dialog-layout>
</template>
四、具体使用
import ChangePasswordDialog from './dialog/changePassword';
this.$dialog.open(ChangePasswordDialog).then(res => {
	this.save();
})
五、如何用 Vue3 的语法来重写 main.js 中的 $dialog 方法?
  1. app.config.globalProperties 代替 Vue.prototype;
  2. 用什么来代替 Vue.extend 呢?这里使用的 createApp;
  3. createApp 代替 Vue.extend 以后遇到的问题,例如:无法使用 ElementPlus 的UI控件、无法解析全局注册的组件
createdApp 代替 Vue.extend 实现创建一个“子类”,实现同样的效果,先看代码

问题1:无法使用 ElementPlus 的UI控件、无法解析全局注册的组件
回答: 使用 createApp 创建出来的应用实例,use ElementPlus,register 里面是我放的全局通用方法和组件
问题2:为什么Dialog.mount 的节点是写死的?而不是 动态 document.createElement ?
回答:实践过程中发现 document.createElement 通过 proxy.$dialog.open(ChangePasswordDialog) 打开正常,但是加上 .then() 就会出现关闭两次才可以正常关闭的情况

app.config.globalProperties.$dialog = {
  open(component, args) {
    return new Promise((resolve, reject) => {
      const Dialog = createApp(component);
      Dialog.use(ElementPlus);
      Dialog.use(register);
      const $vm = Dialog.mount("#Dialog");
      const node = document.body.appendChild($vm.$el);
      $vm.open(args).then(
        (result) => {
          if (resolve) {
            resolve(result);
          }
          node.remove();
        },
        (arg) => {
          if (reject) {
            reject(arg);
          }
          node.remove();
        }
      );
    });
  },
};
具体效果如下

比较灵活,可插拔的通用Dialog
Vue3 如何优雅的使用 createApp 自定义通用Dialog,vue,vue.js,javascript,前端文章来源地址https://www.toymoban.com/news/detail-799523.html

到了这里,关于Vue3 如何优雅的使用 createApp 自定义通用Dialog的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【mars3d】基于vue3的marsgis通用UI库 mars-ui 的使用

    一名脑残程序员的mars-ui心酸使用记录。 通过mars3d的官网我们可以看到,有配套的UI库使用,那么我们如何使用到自己的项目中呢,跟着文章一步一步来吧! 1、引入UI库 ① 安装 ant-design-vue ② 下载基于vue开发的mars3d的源码,直通车: git clone https://gitee.com/marsgis/mars3d-vue-project.gi

    2024年02月09日
    浏览(98)
  • Vue3优雅地监听localStorage变化

    目录 💡前言  💡 为什么要这样做? 💎 思路 💎 实现 🚗 实现中介者模式 🚗 重写localStorage 🚗 实现useStorage hook 💎 测试 🚗 使用localStorage 🚗 监听localStorage变化 🚗 结果         最近在研究框架,也仔细用了Vue3一些功能,今天分享一次我的实践:         原生的

    2024年02月08日
    浏览(53)
  • 自定义通用返回对象

    目的:给返回对象补充一些信息,告诉前端这个请求在业务层面上是成功还是失败,以及具体的描述信息。 我们需要自定义错误码(因为前端的HTTP状态码默认的值比较少)和正常错误返回类。 ErrorCode : BaseResponse: ResultUtil :

    2024年01月24日
    浏览(31)
  • vue3探索——vue3+vite2动态绑定图片优雅解决方案

    优雅解决方案在最下面,小伙伴们儿可以直接前往 😊 在vue3+vite2项目中,我们有时候想要动态绑定资源,比如像下面的代码这样: 实际效果是这样: 我们注意到,控制台的报错信息 GET http://127.0.0.1:5173/1.jpg 404 (Not Found) GET :表示向服务器请求资源的方式。 http://127.0.0.1:5173

    2024年02月10日
    浏览(57)
  • vue3+vite2动态绑定图片优雅解决方案

    优雅解决方案在最下面,小伙伴们儿可以直接前往 😊 在vue3+vite2项目中,我们有时候想要动态绑定资源,比如像下面的代码这样: 实际效果是这样: 我们注意到,控制台的报错信息 GET http://127.0.0.1:5173/1.jpg 404 (Not Found) GET :表示向服务器请求资源的方式。 http://127.0.0.1:5173

    2024年02月11日
    浏览(69)
  • 记录--Vue3 封装 ECharts 通用组件

    配置文件这里就不再赘述,内容都是一样的,主打一个随用随取,按需导入。 chartRef :当前的 DOM 节点,即 ECharts 的容器; chartInstance :当前 DOM 节点挂载的 ECharts 实例,可用于调用实例上的方法,注册事件,自适应等; draw :用于绘制 ECharts 图表,本质是调用实例的 setOptio

    2024年02月09日
    浏览(47)
  • 【vue3】优雅的解决reactive()响应式对象初始化重新赋值问题v2

    关联的上篇文章: 【vue3】优雅的解决reactive()响应式对象初始化重新赋值问题_vue3 reactive重新赋值_oumae-kumiko的博客-CSDN博客 在上面该文章提到了reactive该api的不方便之处和相关重置数据方法的解析。下面提供的方法就是自己封装的`$reactive`方法,通过该方法返回响应式数据和重

    2024年02月15日
    浏览(57)
  • 基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十一:通用表单组件封装实现

      本章实现通用表单组件,根据实体配置识别实体属性,并自动生成编辑组件,实现对应数据填充、校验及保存等逻辑。 1. 详细课程地址: https://edu.csdn.net/course/detail/38183 2. 源码下载地址: 点击下载

    2024年02月10日
    浏览(55)
  • 浅谈Vue3——如何使用Push

    Vue.js是一个流行的JavaScript框架,用于构建用户界面。Vue 3是Vue.js的最新版本,它引入了许多新功能和改进,使得开发更加简单和高效。本文将介绍如何在Vue 3中使用 push 方法以及相应的代码示例。 在Vue 3中,\\\"push\\\"是一个数组方法,用于向数组的末尾添加一个或多个元素。它会

    2024年02月07日
    浏览(43)
  • Vue3 中如何使用this

    Vue2升级到Vue3,有很大的改变,其中最明显的就是以前的this,在新版本中无法使用了,这是为什么呢? 官方是这样说的:在 setup() 内部,this 不会是该活跃实例的引用(即不指向vue实例),因为 setup() 是在解析其它组件选项之前被调用的,所以 setup() 内部的 this 的行为

    2024年02月12日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包