index.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import ResizeObserver from 'resize-observer-polyfill';
  3. import { defineComponent, getCurrentInstance, onMounted, onUnmounted, onUpdated, reactive, watch } from 'vue';
  4. import { findDOMNode } from '../_util/props-util';
  5. export default defineComponent({
  6. compatConfig: {
  7. MODE: 3
  8. },
  9. name: 'ResizeObserver',
  10. props: {
  11. disabled: Boolean,
  12. onResize: Function
  13. },
  14. emits: ['resize'],
  15. setup(props, _ref) {
  16. let {
  17. slots
  18. } = _ref;
  19. const state = reactive({
  20. width: 0,
  21. height: 0,
  22. offsetHeight: 0,
  23. offsetWidth: 0
  24. });
  25. let currentElement = null;
  26. let resizeObserver = null;
  27. const destroyObserver = () => {
  28. if (resizeObserver) {
  29. resizeObserver.disconnect();
  30. resizeObserver = null;
  31. }
  32. };
  33. const onResize = entries => {
  34. const {
  35. onResize
  36. } = props;
  37. const target = entries[0].target;
  38. const {
  39. width,
  40. height
  41. } = target.getBoundingClientRect();
  42. const {
  43. offsetWidth,
  44. offsetHeight
  45. } = target;
  46. /**
  47. * Resize observer trigger when content size changed.
  48. * In most case we just care about element size,
  49. * let's use `boundary` instead of `contentRect` here to avoid shaking.
  50. */
  51. const fixedWidth = Math.floor(width);
  52. const fixedHeight = Math.floor(height);
  53. if (state.width !== fixedWidth || state.height !== fixedHeight || state.offsetWidth !== offsetWidth || state.offsetHeight !== offsetHeight) {
  54. const size = {
  55. width: fixedWidth,
  56. height: fixedHeight,
  57. offsetWidth,
  58. offsetHeight
  59. };
  60. _extends(state, size);
  61. if (onResize) {
  62. // defer the callback but not defer to next frame
  63. Promise.resolve().then(() => {
  64. onResize(_extends(_extends({}, size), {
  65. offsetWidth,
  66. offsetHeight
  67. }), target);
  68. });
  69. }
  70. }
  71. };
  72. const instance = getCurrentInstance();
  73. const registerObserver = () => {
  74. const {
  75. disabled
  76. } = props;
  77. // Unregister if disabled
  78. if (disabled) {
  79. destroyObserver();
  80. return;
  81. }
  82. // Unregister if element changed
  83. const element = findDOMNode(instance);
  84. const elementChanged = element !== currentElement;
  85. if (elementChanged) {
  86. destroyObserver();
  87. currentElement = element;
  88. }
  89. if (!resizeObserver && element) {
  90. resizeObserver = new ResizeObserver(onResize);
  91. resizeObserver.observe(element);
  92. }
  93. };
  94. onMounted(() => {
  95. registerObserver();
  96. });
  97. onUpdated(() => {
  98. registerObserver();
  99. });
  100. onUnmounted(() => {
  101. destroyObserver();
  102. });
  103. watch(() => props.disabled, () => {
  104. registerObserver();
  105. }, {
  106. flush: 'post'
  107. });
  108. return () => {
  109. var _a;
  110. return (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)[0];
  111. };
  112. }
  113. });