BackTop.mjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { ref, watch, computed, Teleport, nextTick, onMounted, defineComponent, onDeactivated, onActivated, createVNode as _createVNode, mergeProps as _mergeProps } from "vue";
  2. import { extend, addUnit, inBrowser, numericProp, getScrollTop, getZIndexStyle, createNamespace, makeNumericProp } from "../utils/index.mjs";
  3. import { throttle } from "../lazyload/vue-lazyload/util.mjs";
  4. import { useEventListener, getScrollParent } from "@vant/use";
  5. import { Icon } from "../icon/index.mjs";
  6. const [name, bem] = createNamespace("back-top");
  7. const backTopProps = {
  8. right: numericProp,
  9. bottom: numericProp,
  10. zIndex: numericProp,
  11. target: [String, Object],
  12. offset: makeNumericProp(200),
  13. immediate: Boolean,
  14. teleport: {
  15. type: [String, Object],
  16. default: "body"
  17. }
  18. };
  19. var stdin_default = defineComponent({
  20. name,
  21. inheritAttrs: false,
  22. props: backTopProps,
  23. emits: ["click"],
  24. setup(props, {
  25. emit,
  26. slots,
  27. attrs
  28. }) {
  29. let shouldReshow = false;
  30. const show = ref(false);
  31. const root = ref();
  32. const scrollParent = ref();
  33. const style = computed(() => extend(getZIndexStyle(props.zIndex), {
  34. right: addUnit(props.right),
  35. bottom: addUnit(props.bottom)
  36. }));
  37. const onClick = (event) => {
  38. var _a;
  39. emit("click", event);
  40. (_a = scrollParent.value) == null ? void 0 : _a.scrollTo({
  41. top: 0,
  42. behavior: props.immediate ? "auto" : "smooth"
  43. });
  44. };
  45. const scroll = () => {
  46. show.value = scrollParent.value ? getScrollTop(scrollParent.value) >= +props.offset : false;
  47. };
  48. const getTarget = () => {
  49. const {
  50. target
  51. } = props;
  52. if (typeof target === "string") {
  53. const el = document.querySelector(target);
  54. if (el) {
  55. return el;
  56. }
  57. if (process.env.NODE_ENV !== "production") {
  58. console.error(`[Vant] BackTop: target element "${target}" was not found, the BackTop component will not be rendered.`);
  59. }
  60. } else {
  61. return target;
  62. }
  63. };
  64. const updateTarget = () => {
  65. if (inBrowser) {
  66. nextTick(() => {
  67. scrollParent.value = props.target ? getTarget() : getScrollParent(root.value);
  68. scroll();
  69. });
  70. }
  71. };
  72. useEventListener("scroll", throttle(scroll, 100), {
  73. target: scrollParent
  74. });
  75. onMounted(updateTarget);
  76. onActivated(() => {
  77. if (shouldReshow) {
  78. show.value = true;
  79. shouldReshow = false;
  80. }
  81. });
  82. onDeactivated(() => {
  83. if (show.value && props.teleport) {
  84. show.value = false;
  85. shouldReshow = true;
  86. }
  87. });
  88. watch(() => props.target, updateTarget);
  89. return () => {
  90. const Content = _createVNode("div", _mergeProps({
  91. "ref": !props.teleport ? root : void 0,
  92. "class": bem({
  93. active: show.value
  94. }),
  95. "style": style.value,
  96. "onClick": onClick
  97. }, attrs), [slots.default ? slots.default() : _createVNode(Icon, {
  98. "name": "back-top",
  99. "class": bem("icon")
  100. }, null)]);
  101. if (props.teleport) {
  102. return [_createVNode("div", {
  103. "ref": root,
  104. "class": bem("placeholder")
  105. }, null), _createVNode(Teleport, {
  106. "to": props.teleport
  107. }, {
  108. default: () => [Content]
  109. })];
  110. }
  111. return Content;
  112. };
  113. }
  114. });
  115. export {
  116. backTopProps,
  117. stdin_default as default
  118. };