Popup源码分析 – ant-design-vue系列
1 极简代码
直接返回两个组件:Mask
和 PopupInner
,后者在上一篇已经分析过了。下面我们先看一下 Mask
的源码。
javascript">setup(props, { slots }) {return () => {if (!props.visible) return null;return (<div class="v-popup">{/* <Mask visible /> */}<PopupInner target={props.target} align={props.align} visible>{slots.default?.()}</PopupInner></div>);};
}
2 Mask源码
这是一个函数式组件,处理过程比较简单,只是调用getMotion
获取了动画类名,给到Transition
组件使用。
但是由于mask
变量在Trigger
中的默认值是false
,在Popup
中也没有单独处理,所以在这里,mask === false
,也就是说dropdown
没有Mask
蒙层。所以在极简代码中也是注释掉的。
javascript">export default function Mask(props: MaskProps) {const { prefixCls, visible, zIndex, mask, maskAnimation, maskTransitionName } = props;// 这里的mask是falseif (!mask) {return null;}let motion = {};if (maskTransitionName || maskAnimation) {motion = getMotion({prefixCls,transitionName: maskTransitionName,animation: maskAnimation,});}return (<Transition appear {...motion}><div v-if={visible} style={{ zIndex }} class={`${prefixCls}-mask`} /></Transition>);
}
- 我们可以找到modal的蒙层,看一下蒙层的css是如何实现的。
绝对定位 + 层级 + 高度 + 背景色
.ant-modal-mask {position: fixed;top: 0;right: 0;bottom: 0;left: 0;z-index: 1000;height: 100%;background-color: rgba(0, 0, 0, 0.45);
}
3 Popup源码
我们把有关mobile的判断去掉,剩下的就是下面的代码。可以看到,因为Mask
组件是null
,所以几乎就是直接渲染了PopupInner
组件。
需要注意的是,这里重新声明了innerVisible
,并且监听props.visible
时使用了 flush: 'post'
。这些都是为了让动画延迟执行。涉及到动画的地方都是这样处理的。
javascript">setup(props, { attrs, slots, expose }) {const innerVisible = ref(false);const popupRef = ref();watch(() => props.visible,() => {innerVisible.value = props.visible;},{ immediate: true, flush: 'post' },);expose({forceAlign: () => {popupRef.value?.forceAlign();},getElement: () => {return popupRef.value?.getElement();},});return () => {const cloneProps = { ...props, ...attrs, visible: innerVisible.value };return (<div><Mask {...cloneProps} /><PopupInner {...cloneProps} ref={popupRef} v-slots={{ default: slots.default }} /></div>);};},
4 总结
Popup
组件到这里就结束了,再来看一下这个整理结构。可以看到:
Popup
作用主要是整合Mask
和PopupInner
。PopupInne
r主要是定义了动画。Align
作用是执行target
和source
的对齐操作。