ant-design-vue/components/vc-resize-observer/index.tsx

140 lines
3.3 KiB
Vue
Raw Normal View History

refactor: Anchor、Alert、Avatar、Badge、BackTop、Col、Form、Layout、Menu、Space、Spin、Switch、Row、Result、Rate (#4171) * chore: remove resize-observer-polyfill * refactor: align * refactor(v3/avatar): refactor using composition api (#4052) * refactor(avatar): refactor using composition api * refactor: update props define * fix: avatar src scale not update * refactor: resizeObserver * refactor: divider * refactor: localeProvider * refactor(v3/back-top): use composition api (#4060) * refactor: backtop * refactor: empty * refactor: transButton * feat(v3/avatar): add avatar group (#4062) * feat(avatar): add avatar group * refactor: update * refactor: update Co-authored-by: tangjinzhou <415800467@qq.com> * refactor: avatar * refactor: avatar * style: rename useProvide * refactor: menu (#4110) * fix: menu * refactor: menu * refactor: remove rc-menu * fix: menu rtl error * style: lint * refactor(Anchor): use composition api (#4054) * refactor: anchor * refactor: anchor * refactor: anchor * feat: update * fix: icon class lose * refactor(v3/badge): use composition api (#4076) * refactor: badge * fix: badge inheritAttrs * refactor: grid * refactor: layout * fix: menu not close * refactor: space * refactor: result * refactor: affix * refactor: comment * refactor: form * feat: spin add rtl * feat: export spin type * refactor: pageHeader * refactor: page-header * refactor: skeleton * refactor: typography * refactor(v3/rate): use composition api * fix: add useRef hook * refactor: form * fix: menu not update * refactor: form * refactor: form * fix: slide animate not work * fix: menu mode error * fix: menu icon * refactor: rate * perf: remove rate * feat: add vc-overflow * refactor: menu * fix: remove flex check (#4165) * fix: dist locale file lose #3684 * release 2.2.0-beta.1 * dcos: update changelog * chore: update type * docs: update changelog Co-authored-by: John <John60676@qq.com> Co-authored-by: 言肆 <18x@loacg.com> Co-authored-by: zkwolf <chenhao5866@gmail.com>
2021-06-07 09:35:03 +00:00
// based on rc-resize-observer 1.0.0
2021-06-26 01:35:40 +00:00
import type { PropType } from 'vue';
refactor: Anchor、Alert、Avatar、Badge、BackTop、Col、Form、Layout、Menu、Space、Spin、Switch、Row、Result、Rate (#4171) * chore: remove resize-observer-polyfill * refactor: align * refactor(v3/avatar): refactor using composition api (#4052) * refactor(avatar): refactor using composition api * refactor: update props define * fix: avatar src scale not update * refactor: resizeObserver * refactor: divider * refactor: localeProvider * refactor(v3/back-top): use composition api (#4060) * refactor: backtop * refactor: empty * refactor: transButton * feat(v3/avatar): add avatar group (#4062) * feat(avatar): add avatar group * refactor: update * refactor: update Co-authored-by: tangjinzhou <415800467@qq.com> * refactor: avatar * refactor: avatar * style: rename useProvide * refactor: menu (#4110) * fix: menu * refactor: menu * refactor: remove rc-menu * fix: menu rtl error * style: lint * refactor(Anchor): use composition api (#4054) * refactor: anchor * refactor: anchor * refactor: anchor * feat: update * fix: icon class lose * refactor(v3/badge): use composition api (#4076) * refactor: badge * fix: badge inheritAttrs * refactor: grid * refactor: layout * fix: menu not close * refactor: space * refactor: result * refactor: affix * refactor: comment * refactor: form * feat: spin add rtl * feat: export spin type * refactor: pageHeader * refactor: page-header * refactor: skeleton * refactor: typography * refactor(v3/rate): use composition api * fix: add useRef hook * refactor: form * fix: menu not update * refactor: form * refactor: form * fix: slide animate not work * fix: menu mode error * fix: menu icon * refactor: rate * perf: remove rate * feat: add vc-overflow * refactor: menu * fix: remove flex check (#4165) * fix: dist locale file lose #3684 * release 2.2.0-beta.1 * dcos: update changelog * chore: update type * docs: update changelog Co-authored-by: John <John60676@qq.com> Co-authored-by: 言肆 <18x@loacg.com> Co-authored-by: zkwolf <chenhao5866@gmail.com>
2021-06-07 09:35:03 +00:00
import {
defineComponent,
getCurrentInstance,
onMounted,
onUnmounted,
onUpdated,
reactive,
watch,
} from 'vue';
import { findDOMNode } from '../_util/props-util';
interface ResizeObserverState {
height: number;
width: number;
offsetHeight: number;
offsetWidth: number;
}
const ResizeObserver = defineComponent({
name: 'ResizeObserver',
props: {
disabled: Boolean,
onResize: Function as PropType<
(
size: {
width: number;
height: number;
offsetWidth: number;
offsetHeight: number;
},
element: HTMLElement,
) => void
>,
},
emits: ['resize'],
setup(props, { slots }) {
const state = reactive<ResizeObserverState>({
width: 0,
height: 0,
offsetHeight: 0,
offsetWidth: 0,
});
let currentElement: Element | null = null;
let resizeObserver: ResizeObserver | null = null;
const destroyObserver = () => {
if (resizeObserver) {
resizeObserver.disconnect();
resizeObserver = null;
}
};
const onResize: ResizeObserverCallback = (entries: ResizeObserverEntry[]) => {
const { onResize } = props;
const target = entries[0].target as HTMLElement;
const { width, height } = target.getBoundingClientRect();
const { offsetWidth, offsetHeight } = target;
/**
* Resize observer trigger when content size changed.
* In most case we just care about element size,
* let's use `boundary` instead of `contentRect` here to avoid shaking.
*/
const fixedWidth = Math.floor(width);
const fixedHeight = Math.floor(height);
if (
state.width !== fixedWidth ||
state.height !== fixedHeight ||
state.offsetWidth !== offsetWidth ||
state.offsetHeight !== offsetHeight
) {
const size = { width: fixedWidth, height: fixedHeight, offsetWidth, offsetHeight };
Object.assign(state, size);
if (onResize) {
// defer the callback but not defer to next frame
Promise.resolve().then(() => {
onResize(
{
...size,
offsetWidth,
offsetHeight,
},
target,
);
});
}
}
};
const instance = getCurrentInstance();
const registerObserver = () => {
const { disabled } = props;
// Unregister if disabled
if (disabled) {
destroyObserver();
return;
}
// Unregister if element changed
const element = findDOMNode(instance) as Element;
const elementChanged = element !== currentElement;
if (elementChanged) {
destroyObserver();
currentElement = element;
}
if (!resizeObserver && element) {
resizeObserver = new window.ResizeObserver(onResize);
resizeObserver.observe(element);
}
};
onMounted(() => {
registerObserver();
});
onUpdated(() => {
registerObserver();
});
onUnmounted(() => {
destroyObserver();
});
watch(
() => props.disabled,
() => {
registerObserver();
},
{ flush: 'post' },
);
return () => {
return slots.default?.()[0];
};
},
});
export default ResizeObserver;