文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Vue中怎么封装Dialog

2023-06-20 15:21

关注

Vue中怎么封装Dialog,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

解决方案有两个:
  1. 在根组件里面引入动态组件,在业务里面通过this.$root.openDialog(name, props)去控制动态组件的展示形式

  2. 封装成插件的形式去调用,比如this.$dialog('EditDialog.vue', props)

当然了,业务 Dialog 组件要有一套规范,props 接收一个 onOk、onCancel 回调,data 里面定义一个 visible 属性

<template>  <el-dialog :title="title" :visible.sync="visible" append-to-body>    <!-- 业务代码 -->  </el-dialog></template><script>export default {  props: ['onOk', '其他业务需要的属性'],  data() {    return {      visible: false    }  }}</script>

Vue2 写法

在 Vue2 里面我个人感觉写成插件是比较好用的,实现如下,使用混入做了一些操作,和业务进行解耦

有点不太好的地方是组件是动态插入的,Vue devtools 要刷新下才能看到组件

const mixin = {  mounted() {    document.body.appendChild(this.$el)    this.visible = true  },  watch: {    visible(value) {      // 动画结束后销毁实例      if (value === false) {        setTimeout(() => {          this.$destroy()          if (this.$el && this.$el.parentNode) {            this.$el.parentNode.removeChild(this.$el)          }        }, 400)      }    }  }}export default {  install(Vue, options) {    Vue.prototype.$dialog = (name, props) => {      // 相对于该插件的位置,静态编译期间会检查的      import('../components/dialogs/' + name)        .then(module => {          const component = module.default          const mixins = component.mixins || []          mixins.push(mixin) // 实现自动打开,动态了混入生命周期函数和销毁操作          component.mixins = mixins          return Vue.extend(component)        })        .then(Dialog => {          const dialog = new Dialog({            propsData: props || {}          })          dialog.$mount()        })    }  }}

调用方式如下,注意 onOk 回调的 this 指向,使用箭头函数直接就避免了 ?

this.$dialog('GroupEdit.vue', {  type: 'edit',  group: {},  onOk: () => {    this.freshList()  }})

Vue3 插件版写法

很糟糕的是,由于 Vue3 的升级Vue.extend没有了,$mount也没有了,组件只能在应用里面去渲染

每个应用之间的数据是隔离的,所以插件什么的都要重新引入。同时如果要交互交互的话也比较麻烦,引入同一个 vuex 实例应该可以,但是没怎试

为了低耦合只能去新建一个应用去挂载渲染

Vue中怎么封装Dialog

import { createApp, defineComponent } from 'vue'import ElementPlus from 'element-plus'const mixin = {  mounted() {    document.body.appendChild(this.$el)    this.visible = true  },  watch: {    visible(value) {      // 动画结束后销毁实例      if (value === false) {        setTimeout(() => {          this.$.appContext.app.unmount()        }, 400)      }    }  }}export default {  install(app) {    app.config.globalProperties.$dialog = (name, props) => {      import('../components/dialogs/' + name)        .then(module => {          const component = module.default          let mixins = component.mixins || []          mixins.push(mixin)          component.mixins = mixins          return defineComponent(component)        })        .then(Dialog => {          const app = createApp(Dialog, props || {})          app.use(ElementPlus)          app.mount(document.createElement('div'))        })    }  }}

Vue3 动态组件写法

在 Vue3 里面,插件版的写法同样达到了要求,但是完全是一个新引应用了,如果在业务里访问this.$root,vuex,router还是有点麻烦的

所以 Vue3 里面还是动态组件的写法比较好

在根组件引入动态 component,定义一些控制变量

<template>  <router-view></router-view>  <component :is="currentDialog" v-bind="currentDialogProps" /></template><script>export default {  data() {    return {      currentDialog: null,      currentDialogProps: null    }  }}</script>

调用的的话this.$root.$dialog(),看起来太难看,其实还是可以手动模拟插件的效果的

const app = createApp(App)const vm = app.mount('#app')initDialog(app, vm)function initDialog(app, vm) {  const mixin = {    mounted() {      this.visible = true    },    watch: {      visible(value) {        // 动画结束后销毁实例        if (value === false) {          setTimeout(() => {            this.$root.currentDialog = null            this.$root.currentDialogProps = {}          }, 400)        }      }    }  }  app.config.globalProperties.$dialog = (name, props) => {    import('./components/dialogs/' + name).then(module => {      const component = module.default      let mixins = component.mixins || []      mixins.push(mixin)      component.mixins = mixins      // 不需要 defineComponent(component)      vm.currentDialog = markRaw(component)      vm.currentDialogProps = markRaw(props || {})    })  }}

一些比较 hack 的写法

vue3 组件实例获取应用实例

vm.$.appContext.app == app

vue3 应用实例获取组件实例,注意_instance 仅在 dev 环境能访问到

app._instance.proxy == vmapp._instance.root.proxy == vmapp._instance.ctx.$root == vm

骚操作还是有的,但是最好不要用

const app = createApp(App)const vm = app.mount('#app')if (process.env.NODE_ENV === 'production') {  app._instance = {    proxy: vm,    root: {      proxy: vm    },    ctx: {      $root: vm    }  }}

关于Vue中怎么封装Dialog问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网行业资讯频道了解更多相关知识。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯