mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-03 12:37:42 +08:00
refactor: affix by ts
This commit is contained in:
parent
f48ccdac01
commit
2185458744
@ -1,4 +1,4 @@
|
|||||||
import { inject } from 'vue';
|
import { App, CSSProperties, defineComponent, inject } from 'vue';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
import omit from 'omit.js';
|
import omit from 'omit.js';
|
||||||
@ -18,6 +18,17 @@ import {
|
|||||||
function getDefaultTarget() {
|
function getDefaultTarget() {
|
||||||
return typeof window !== 'undefined' ? window : null;
|
return typeof window !== 'undefined' ? window : null;
|
||||||
}
|
}
|
||||||
|
enum AffixStatus {
|
||||||
|
None,
|
||||||
|
Prepare,
|
||||||
|
}
|
||||||
|
export interface AffixState {
|
||||||
|
affixStyle?: CSSProperties;
|
||||||
|
placeholderStyle?: CSSProperties;
|
||||||
|
status: AffixStatus;
|
||||||
|
lastAffix: boolean;
|
||||||
|
prevTarget: Window | HTMLElement | null;
|
||||||
|
}
|
||||||
|
|
||||||
// Affix
|
// Affix
|
||||||
const AffixProps = {
|
const AffixProps = {
|
||||||
@ -36,11 +47,7 @@ const AffixProps = {
|
|||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
onTestUpdatePosition: PropTypes.func,
|
onTestUpdatePosition: PropTypes.func,
|
||||||
};
|
};
|
||||||
const AffixStatus = {
|
const Affix = defineComponent({
|
||||||
None: 'none',
|
|
||||||
Prepare: 'Prepare',
|
|
||||||
};
|
|
||||||
const Affix = {
|
|
||||||
name: 'AAffix',
|
name: 'AAffix',
|
||||||
props: AffixProps,
|
props: AffixProps,
|
||||||
mixins: [BaseMixin],
|
mixins: [BaseMixin],
|
||||||
@ -49,6 +56,7 @@ const Affix = {
|
|||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
configProvider: inject('configProvider', defaultConfigProvider),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
emits: ['change', 'testUpdatePosition'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
affixStyle: undefined,
|
affixStyle: undefined,
|
||||||
@ -56,6 +64,7 @@ const Affix = {
|
|||||||
status: AffixStatus.None,
|
status: AffixStatus.None,
|
||||||
lastAffix: false,
|
lastAffix: false,
|
||||||
prevTarget: null,
|
prevTarget: null,
|
||||||
|
timeout: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
@ -103,9 +112,9 @@ const Affix = {
|
|||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
clearTimeout(this.timeout);
|
clearTimeout(this.timeout);
|
||||||
removeObserveTarget(this);
|
removeObserveTarget(this);
|
||||||
this.updatePosition.cancel();
|
(this.updatePosition as any).cancel();
|
||||||
// https://github.com/ant-design/ant-design/issues/22683
|
// https://github.com/ant-design/ant-design/issues/22683
|
||||||
this.lazyUpdatePosition.cancel();
|
(this.lazyUpdatePosition as any).cancel();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getOffsetTop() {
|
getOffsetTop() {
|
||||||
@ -152,9 +161,9 @@ const Affix = {
|
|||||||
|
|
||||||
const newState = {
|
const newState = {
|
||||||
status: AffixStatus.None,
|
status: AffixStatus.None,
|
||||||
};
|
} as AffixState;
|
||||||
const targetRect = getTargetRect(targetNode);
|
const targetRect = getTargetRect(targetNode);
|
||||||
const placeholderReact = getTargetRect(this.$refs.placeholderNode);
|
const placeholderReact = getTargetRect(this.$refs.placeholderNode as HTMLElement);
|
||||||
const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop);
|
const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop);
|
||||||
const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom);
|
const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom);
|
||||||
if (fixedTop !== undefined) {
|
if (fixedTop !== undefined) {
|
||||||
@ -218,7 +227,7 @@ const Affix = {
|
|||||||
const targetNode = target();
|
const targetNode = target();
|
||||||
if (targetNode && this.$refs.placeholderNode) {
|
if (targetNode && this.$refs.placeholderNode) {
|
||||||
const targetRect = getTargetRect(targetNode);
|
const targetRect = getTargetRect(targetNode);
|
||||||
const placeholderReact = getTargetRect(this.$refs.placeholderNode);
|
const placeholderReact = getTargetRect(this.$refs.placeholderNode as HTMLElement);
|
||||||
const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop);
|
const fixedTop = getFixedTop(placeholderReact, targetRect, offsetTop);
|
||||||
const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom);
|
const fixedBottom = getFixedBottom(placeholderReact, targetRect, offsetBottom);
|
||||||
|
|
||||||
@ -256,10 +265,9 @@ const Affix = {
|
|||||||
</ResizeObserver>
|
</ResizeObserver>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
Affix.install = function(app) {
|
Affix.install = function(app: App) {
|
||||||
app.component(Affix.name, Affix);
|
app.component(Affix.name, Affix);
|
||||||
};
|
};
|
||||||
|
|
@ -1,22 +1,34 @@
|
|||||||
import addEventListener from '../vc-util/Dom/addEventListener';
|
import addEventListener from '../vc-util/Dom/addEventListener';
|
||||||
|
import { ComponentPublicInstance } from 'vue';
|
||||||
|
|
||||||
export function getTargetRect(target) {
|
export type BindElement = HTMLElement | Window | null | undefined;
|
||||||
|
export type Rect = ClientRect | DOMRect;
|
||||||
|
|
||||||
|
export function getTargetRect(target: BindElement): ClientRect {
|
||||||
return target !== window
|
return target !== window
|
||||||
? target.getBoundingClientRect()
|
? (target as HTMLElement).getBoundingClientRect()
|
||||||
: { top: 0, bottom: window.innerHeight };
|
: ({ top: 0, bottom: window.innerHeight } as ClientRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFixedTop(placeholderReact, targetRect, offsetTop) {
|
export function getFixedTop(
|
||||||
|
placeholderReact: Rect,
|
||||||
|
targetRect: Rect,
|
||||||
|
offsetTop: number | undefined,
|
||||||
|
) {
|
||||||
if (offsetTop !== undefined && targetRect.top > placeholderReact.top - offsetTop) {
|
if (offsetTop !== undefined && targetRect.top > placeholderReact.top - offsetTop) {
|
||||||
return offsetTop + targetRect.top + 'px';
|
return `${offsetTop + targetRect.top}px`;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFixedBottom(placeholderReact, targetRect, offsetBottom) {
|
export function getFixedBottom(
|
||||||
|
placeholderReact: Rect,
|
||||||
|
targetRect: Rect,
|
||||||
|
offsetBottom: number | undefined,
|
||||||
|
) {
|
||||||
if (offsetBottom !== undefined && targetRect.bottom < placeholderReact.bottom + offsetBottom) {
|
if (offsetBottom !== undefined && targetRect.bottom < placeholderReact.bottom + offsetBottom) {
|
||||||
const targetBottomOffset = window.innerHeight - targetRect.bottom;
|
const targetBottomOffset = window.innerHeight - targetRect.bottom;
|
||||||
return offsetBottom + targetBottomOffset + 'px';
|
return `${offsetBottom + targetBottomOffset}px`;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -32,17 +44,26 @@ const TRIGGER_EVENTS = [
|
|||||||
'load',
|
'load',
|
||||||
];
|
];
|
||||||
|
|
||||||
let observerEntities = [];
|
interface ObserverEntity {
|
||||||
|
target: HTMLElement | Window;
|
||||||
|
affixList: ComponentPublicInstance<any>[];
|
||||||
|
eventHandlers: { [eventName: string]: any };
|
||||||
|
}
|
||||||
|
|
||||||
|
let observerEntities: ObserverEntity[] = [];
|
||||||
|
|
||||||
export function getObserverEntities() {
|
export function getObserverEntities() {
|
||||||
// Only used in test env. Can be removed if refactor.
|
// Only used in test env. Can be removed if refactor.
|
||||||
return observerEntities;
|
return observerEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addObserveTarget(target, affix) {
|
export function addObserveTarget(
|
||||||
|
target: HTMLElement | Window | null,
|
||||||
|
affix: ComponentPublicInstance<any>,
|
||||||
|
): void {
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
let entity = observerEntities.find(item => item.target === target);
|
let entity: ObserverEntity | undefined = observerEntities.find(item => item.target === target);
|
||||||
|
|
||||||
if (entity) {
|
if (entity) {
|
||||||
entity.affixList.push(affix);
|
entity.affixList.push(affix);
|
||||||
@ -56,16 +77,16 @@ export function addObserveTarget(target, affix) {
|
|||||||
|
|
||||||
// Add listener
|
// Add listener
|
||||||
TRIGGER_EVENTS.forEach(eventName => {
|
TRIGGER_EVENTS.forEach(eventName => {
|
||||||
entity.eventHandlers[eventName] = addEventListener(target, eventName, () => {
|
entity!.eventHandlers[eventName] = addEventListener(target, eventName, () => {
|
||||||
entity.affixList.forEach(targetAffix => {
|
entity!.affixList.forEach(targetAffix => {
|
||||||
targetAffix.lazyUpdatePosition();
|
(targetAffix as any).lazyUpdatePosition();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeObserveTarget(affix) {
|
export function removeObserveTarget(affix: ComponentPublicInstance<any>): void {
|
||||||
const observerEntity = observerEntities.find(oriObserverEntity => {
|
const observerEntity = observerEntities.find(oriObserverEntity => {
|
||||||
const hasAffix = oriObserverEntity.affixList.some(item => item === affix);
|
const hasAffix = oriObserverEntity.affixList.some(item => item === affix);
|
||||||
if (hasAffix) {
|
if (hasAffix) {
|
@ -2,8 +2,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
"paths": {
|
"paths": {
|
||||||
"ant-design-vue": ["components/index.tsx"],
|
"ant-design-vue": ["components/index.tsx"]
|
||||||
"ant-design-vue/es/*": ["components/*"]
|
|
||||||
},
|
},
|
||||||
"strictNullChecks": false,
|
"strictNullChecks": false,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user