使用函数优雅地创建 ant-design-vue、view-design、ElementUI 的 Drawer 和 Modal
例子
特性
- 通过函数来创建
Modal
或Drawer
组件 Modal
、Drawer
的内容子组件的created
、mounted
、destoryed
生命周期按照正常逻辑触发Modal
、Drawer
支持分别注册全局头部组件(需要接收名为title
的props
)- 支持传入
title
、content
、footer
插槽 - 支持
Modal
、Drawer
与父组件通信 - 支持子组件获取
this.$store
和this.$router
- 支持传入路由来匹配内容组件,
- 若传入
url
比如 https://www.baidu.com ,则以iframe
形式展示 - 若传入
相对路由
(比如 /foo, /bar),则获取匹配的路由组件展示
- 若传入
- 支持微前端中跨项目相互调用
为什么
在使用弹窗抽屉组件的过程中,你是否也曾遇到过以下场景:
一个项目里有许多的弹窗和抽屉类型的交互,有时甚至一个页面组件里就有许多弹窗和抽屉组件,原生的使用方式是先在父组件中写好弹框抽屉组件,然后通过
visible
变量来控制弹窗的显示隐藏,当弹窗抽屉一多,看着各种xxVisible
让人感觉很混乱弹窗抽屉内包含的子组件的生命周期并没有按我们预想的逻辑触发,我们想打开弹窗抽屉的时候才触发内容子组件的
created
和mounted
生命周期,然而实际上却并不是;我们希望关闭的时候可以调用子组件的destoryed
生命周期,可是目前的UI框架大多只是把组件设置为display:none
了,并没有完全卸载子组件,antd
提供了destroyOnClose
参数支持关闭时销毁子元素,但也没法解决上面说到的1,2两点问题组件库虽然也有提供通过函数打开弹窗的方法,但那些都是一些简单的弹框,可配置的参数不多,自由度也不够高
因此就有了vue-create-dm
这个库,dm
就是分别取了Drawer
和Modal
的第一个字母组合在一起(为什么不是md
呢,因为md
是markdown
的缩写…)目前内置支持了ant-design-vue
、view-design
和ElementUI
三个组件库的的弹框抽屉组件,并且提供了各种工具函数可以自己支持其他组件库的弹框抽屉组件
安装
1 | yarn add vue-create-dm |
统一注册
注意1
如果要在子组件内获取 this.$store
和 this.$router
请把 VueCreateDM
的注册放到 Vuex
和 VueRouter
实例生成之后,并且传入这两个实例
注意2
如果要自定义全局头部组件,请传入modalGlobalHeader
,drawerGlobalHeader
这两个参数,分别对应Modal
组件的全局头部和Drawer
组件的全局头部
下面演示如何进行全量注册:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import Vue from 'vue';
import VueCreateDM from 'vue-create-dm';
import { Modal as antdModal, Drawer as antdDrawer } from 'ant-design-vue';
import { Modal as viewModal, Drawer as viewDrawer } from 'view-design';
import { Dialog as eleModal, Drawer as eleDrawer } from 'element-ui';
import store from './store'
import router from './router';
import modalGlobalHeader from './components/modalGlobalHeader';
import drawerGlobalHeader from './components/drawerGlobalHeader';
Vue.use(VueCreateDM, {
antdModal,
antdDrawer,
viewModal,
viewDrawer,
eleModal,
eleDrawer,
store,
router,
modalGlobalHeader,
drawerGlobalHeader,
});
单个注册
注意1
如果要在子组件内获取 this.$store
和 this.$router
请把 VueCreateDM
的注册放到 Vuex
和 VueRouter
实例生成之后,并且传入这两个实例
注意2
如果要自定义全局头部组件,请传入globalHeader
参数
下面演示如何单个注册,其中component
属性必传,其余几个都是可选参数:1
2
3
4
5
6
7
8
9
10
11
12
13import Vue from 'vue';
import store from './store';
import router from './router';
import { createAntdDrawer } from 'vue-create-dm';
import { Drawer } from 'ant-design-vue';
import globalHeader from '../components/globalHeader';
Vue.use(createAntdDrawer, {
component: Drawer,
router, // 子组件需要用到 this.$router 就传
store // 子组件需要用到 this.$store 就传
globalHeader, // 全局配置头部组件
});
使用
创建抽屉
1 | this.$createAntdDrawer(options, arg1, arg2); |
代码示例
1 | this.$createAntdDrawer({ |
创建弹框
1 | this.$createAntdModal(options, arg1, arg2); |
代码示例
1 | this.$createAntdModal({ |
微前端中使用
基于single-spa, vue-create-dm也支持在微前端项目中跨项目调用抽屉、弹框
前提条件
- 需要互相调用抽屉、弹框的子项目必须都是 vue 技术栈
- 并且都安装注册了vue-create-dm
- 要跨项目调用的页面注册成路由页面
示例项目
参考 micro-frontend-example 文件夹
主项目使用
注册子应用的方式需要改成config配置文件的方式。
1
2
3
4
5
6
7
8
9const config = [{
name: 'sub1',
app: () => loadSubApp('sub1', 'http://localhost:8081/manifest-initial.json'),
activeWhen: (location) => location.pathname.startsWith('/sub1'),
customProps: {
domElement: '#app-sub-wrapper',
},
}]
export default config;main.js加入如下代码
1
2
3
4
5
6import { listenOpenDrawerAction, triggerOpenDrawerAction } from 'vue-create-dm';
import config from './micro-frontend/config/config';
// 监听打开抽屉事件
listenOpenDrawerAction(config, '$createAntdDrawer');
// 子项目调用打开抽屉的函数
window.triggerOpenDrawerAction = triggerOpenDrawerAction;
子项目使用
除了 single-spa 要求导出的生命周期方法之外,子项目的
main.js
需要额外导出一个router
实例和一个空的vue
实例。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import Vue from 'vue';
import router from './router';
import store from './store';
import VueCreateDM from 'vue-create-dm';
import { Modal as antdModal, Drawer as antdDrawer } from 'ant-design-vue';
Vue.use(VueCreateDM, {
antdDrawer,
antdModal,
router,
store,
});
export const bootstrap = function(){...}
export const mount = function(){...}
export const unmount = function(){...}
export const update = function(){...}
// 额外导出
export const $router = router;
export const $Vue = new Vue();需要被跨项目调用的组件,请在子项目的VueRouter路由配置文件中声明
- 子项目触发
openDrawer
、openModal
事件1
2
3
4
5
6
7
8
9window.triggerOpenDrawerAction({
appName: 'sub2',
path: '/about',
drawerProps: {
title: '子应用二抽屉',
width: '50%',
},
content: {},
});
PS: 如果觉得不错, 欢迎前往 Github vue-create-dm 点个star
友情链接: