BackTop.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _extends from "@babel/runtime/helpers/esm/extends";
  3. import { withDirectives as _withDirectives, vShow as _vShow, createVNode as _createVNode } from "vue";
  4. import VerticalAlignTopOutlined from "@ant-design/icons-vue/es/icons/VerticalAlignTopOutlined";
  5. import { getTransitionProps, Transition } from '../_util/transition';
  6. import { defineComponent, nextTick, onActivated, onBeforeUnmount, onMounted, reactive, ref, watch, onDeactivated } from 'vue';
  7. import FloatButton, { floatButtonPrefixCls } from './FloatButton';
  8. import useConfigInject from '../config-provider/hooks/useConfigInject';
  9. import getScroll from '../_util/getScroll';
  10. import scrollTo from '../_util/scrollTo';
  11. import throttleByAnimationFrame from '../_util/throttleByAnimationFrame';
  12. import { initDefaultProps } from '../_util/props-util';
  13. import { backTopProps } from './interface';
  14. import useStyle from './style';
  15. import { useInjectFloatButtonGroupContext } from './context';
  16. const BackTop = defineComponent({
  17. compatConfig: {
  18. MODE: 3
  19. },
  20. name: 'ABackTop',
  21. inheritAttrs: false,
  22. props: initDefaultProps(backTopProps(), {
  23. visibilityHeight: 400,
  24. target: () => window,
  25. duration: 450,
  26. type: 'default',
  27. shape: 'circle'
  28. }),
  29. // emits: ['click'],
  30. setup(props, _ref) {
  31. let {
  32. slots,
  33. attrs,
  34. emit
  35. } = _ref;
  36. const {
  37. prefixCls,
  38. direction
  39. } = useConfigInject(floatButtonPrefixCls, props);
  40. const [wrapSSR] = useStyle(prefixCls);
  41. const domRef = ref();
  42. const state = reactive({
  43. visible: props.visibilityHeight === 0,
  44. scrollEvent: null
  45. });
  46. const getDefaultTarget = () => domRef.value && domRef.value.ownerDocument ? domRef.value.ownerDocument : window;
  47. const scrollToTop = e => {
  48. const {
  49. target = getDefaultTarget,
  50. duration
  51. } = props;
  52. scrollTo(0, {
  53. getContainer: target,
  54. duration
  55. });
  56. emit('click', e);
  57. };
  58. const handleScroll = throttleByAnimationFrame(e => {
  59. const {
  60. visibilityHeight
  61. } = props;
  62. const scrollTop = getScroll(e.target, true);
  63. state.visible = scrollTop >= visibilityHeight;
  64. });
  65. const bindScrollEvent = () => {
  66. const {
  67. target
  68. } = props;
  69. const getTarget = target || getDefaultTarget;
  70. const container = getTarget();
  71. handleScroll({
  72. target: container
  73. });
  74. container === null || container === void 0 ? void 0 : container.addEventListener('scroll', handleScroll);
  75. };
  76. const scrollRemove = () => {
  77. const {
  78. target
  79. } = props;
  80. const getTarget = target || getDefaultTarget;
  81. const container = getTarget();
  82. handleScroll.cancel();
  83. container === null || container === void 0 ? void 0 : container.removeEventListener('scroll', handleScroll);
  84. };
  85. watch(() => props.target, () => {
  86. scrollRemove();
  87. nextTick(() => {
  88. bindScrollEvent();
  89. });
  90. });
  91. onMounted(() => {
  92. nextTick(() => {
  93. bindScrollEvent();
  94. });
  95. });
  96. onActivated(() => {
  97. nextTick(() => {
  98. bindScrollEvent();
  99. });
  100. });
  101. onDeactivated(() => {
  102. scrollRemove();
  103. });
  104. onBeforeUnmount(() => {
  105. scrollRemove();
  106. });
  107. const floatButtonGroupContext = useInjectFloatButtonGroupContext();
  108. return () => {
  109. const {
  110. description,
  111. type,
  112. shape,
  113. tooltip,
  114. badge
  115. } = props;
  116. const floatButtonProps = _extends(_extends({}, attrs), {
  117. shape: (floatButtonGroupContext === null || floatButtonGroupContext === void 0 ? void 0 : floatButtonGroupContext.shape.value) || shape,
  118. onClick: scrollToTop,
  119. class: {
  120. [`${prefixCls.value}`]: true,
  121. [`${attrs.class}`]: attrs.class,
  122. [`${prefixCls.value}-rtl`]: direction.value === 'rtl'
  123. },
  124. description,
  125. type,
  126. tooltip,
  127. badge
  128. });
  129. const transitionProps = getTransitionProps('fade');
  130. return wrapSSR(_createVNode(Transition, transitionProps, {
  131. default: () => [_withDirectives(_createVNode(FloatButton, _objectSpread(_objectSpread({}, floatButtonProps), {}, {
  132. "ref": domRef
  133. }), {
  134. icon: () => {
  135. var _a;
  136. return ((_a = slots.icon) === null || _a === void 0 ? void 0 : _a.call(slots)) || _createVNode(VerticalAlignTopOutlined, null, null);
  137. }
  138. }), [[_vShow, state.visible]])]
  139. }));
  140. };
  141. }
  142. });
  143. export default BackTop;