vc-align源码分析
源码地址:https://github.com/vueComponent/ant-design-vue/tree/main/components/vc-align
1 基础代码
1.1 名词约定
需要对齐的节点叫source
,对齐的目标叫target
。
1.2 props
提供了两个参数:
align
:对齐的配置target
:一个函数,用于获取对齐的目标dom
1.3 主要逻辑
- 增加了一个
dom
,用来挂载source
节点,同时拿到它的引用。 - 提供了一个方法
align
,在组件初始化/定位方式改变/对齐目标改变的时候,重新执行对齐方法。
代码如下:
import {
defineComponent, ref, onMounted, watch, PropType } from 'vue';
import {
alignElement } from 'dom-align';
import {
AlignType, TargetType } from './interface';
export default defineComponent({
name: 'Align',
props: {
align: {
type: Object as PropType<AlignType>,
required: true
},
target: {
type: [Object, Function] as PropType<TargetType>,
required: true
}
},
setup(props, {
slots }) {
const nodeRef = ref<HTMLElement | null>(null);
/**
* 用来对齐的方法
*/
const align = () => {
if (!nodeRef.value) return;
const {
align: latestAlign, target: latestTarget } = props;
let result: any;
let targetElement: HTMLElement | null = null;
if (typeof latestTarget === 'function') {
targetElement = latestTarget();
}
if (targetElement && targetElement.nodeType === Node.ELEMENT_NODE) {
/**
* 调用对齐的库方法
*/
result = alignElement(nodeRef.value, targetElement, latestAlign);
}
};
onMounted(() => {
align();
});
/**
* 监控对齐方式和target的改变,重新执行对齐
*/
watch(
() => [props.align, props.target],
() => {
align();
},
{
immediate: true, deep: true, flush: 'post' }
);
return () => {
const child = slots.default?.();
if (child) {
return <div ref={
nodeRef}>{
child}</div>;
}
return null;
};
}
});
1.4 补充:dom-align 库
官方地址:https://yiminghe.me/dom-align/
1.4.1 基础用法
import domAlign from 'dom-align';
// use domAlign
// sourceNode's initial style should be position:absolute;left:-9999px;top:-9999px;
const alignConfig = {
points: ['tl', 'tr'],