H5W3
当前位置:H5W3 > 其他技术问题 > 正文

【前端技术】通过函数创建 ant-design-vue 的 Drawer 组件和 Modal 组件

原由

通常在业务中,写抽屉组件或者弹框组件的时候,都是用 visible 属性来控制是否显示:

<template>
  <div>
    <a-button type="primary" @click="showModal">
      Open Modal with async logic
    </a-button>
    <a-modal
      title="Title"
      :visible="visible"
      :confirm-loading="confirmLoading"
      @ok="handleOk"
      @cancel="handleCancel"
    >
      <p>{{ ModalText }}</p>
    </a-modal>
  </div>
</template>
<script>
export default {
  data() {
    return {
      ModalText: 'Content of the modal',
      visible: false,
      confirmLoading: false,
    };
  },
  methods: {
    showModal() {
      this.visible = true;
    },
    handleOk(e) {
      this.ModalText = 'The modal will be closed after two seconds';
      this.confirmLoading = true;
      setTimeout(() => {
        this.visible = false;
        this.confirmLoading = false;
      }, 2000);
    },
    handleCancel(e) {
      console.log('Clicked cancel button');
      this.visible = false;
    },
  },
};
</script>

这种写法在组件比较简单,逻辑不多的时候还好,当这个页面又许多弹框,或者当前页面组件本身就比较复杂的时候,各种 isXXVisible 充斥在当前页面中,让人看着就无力维护…

还有一个场景,一个列表有个查看详情按钮,点击会打开一个详情抽屉,这个详情抽屉里又有一个列表,也能打开另一个详情抽屉,以此类推。没法确定要打开的弹窗的数量,也就没法提前在父组件中写好弹窗…

从逻辑上来说,这种用一个变量来控制组件显隐的做法,是把弹窗或抽屉组件当成了当前组件的一个子组件。但是在绝大多数情况下,弹窗或抽屉的内容跟原组件都没太大关联,比如抽屉打开详情页,比如弹窗打开一个表单等等,逻辑上更像是一个独立的子应用那样,这个子应用接收调起它的父应用传过来的一些参数,但之后整个页面的控制权就应该交给这个子应用(弹窗或抽屉),主应用应该只是监听 子应用 退出的事件(回调结果)后作出相应的响应才对。

因此,我的想法是通过调用一个函数,并传入一些相应的props参数来创建弹窗或者抽屉,同时提供回调函数在弹窗提交结果或者取消时进行响应。这样我们可以很方便的把弹窗的逻辑内聚到弹窗组件上,而不用在父组件里写很多和父组件无关的逻辑。

函数用法介绍

1. createAntdDrawer

默认会往 titlecontent 这两个 slot 插槽内传入一个名为 close 的函数,在子组件内使用 this.$emit('close', payload) 触发关闭行为

createAntdDrawer({
  // antd drawer 的所有props
  drawerProps: {},
  // title slot
  // drawerProps.title 和 title 同时存在的话,优先使用 title
  title: {
    template: Title,
    props: {
      title: '自定义标题组件',
    },
  },
  // default slot
  content: {
    template: HelloWorld,
    props: {
      msg: 'Welcome to Your Vue.js App',
    },
  },
  // 关闭前调用 支持async
  beforeClose: function() {
    console.log('我要关闭了');
  },
  // 关闭后调用 支持async
  afterClose: function() {
    console.log('我已经关闭了');
  },
});

2. createAntdModal

会往 titlecontentfooter 这三个 slot 插槽内传入 closeok 两个函数和 confirmLoading这一状态, 在子组件内使用 this.$emit('close', payload) 触发关闭动作, 使用 this.$emit('ok', payload) 触发 onOk 回调。子组件内可以使用 confirmLoading 来管理确定按钮的加载状态

createAntdModal({
  // antd modal 的所有props
  modalProps: {},
  // title slot
  // modalProps.title 和 title 同时存在的话,优先使用 title
  title: {
    template: Title,
    props: {
      title: '自定义标题组件',
    },
  },
  // content slot
  content: {
    template: HelloWorld,
    props: {
      msg: 'Welcome to Your Vue.js App',
    },
  },
  // footer slot
  footer: {
    template: Footer,
    props: {
      cancelText: 'hahah取消',
      okText: 'hahah确定',
    },
  },
  // 关闭前调用 支持async
  beforeClose: function() {
    console.log('我要关闭了');
  },
  // 关闭后调用 支持async
  afterClose: function() {
    console.log('我已经关闭了');
  },
  // 确定按钮回调 支持async
  async onOk() {
    await new Promise((resolve) => {
      setTimeout(() => {
        console.log('点了确定');
        resolve();
      }, 3000);
    });
  },
});

git地址

https://github.com/hzyhbk/cre…

clone 整个项目,安装下依赖,然后 npm run serve,会在首页看到两个按钮,点击即可查看效果。

欢迎star。

本文地址:H5W3 » 【前端技术】通过函数创建 ant-design-vue 的 Drawer 组件和 Modal 组件

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址