91 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Vue
		
	
	
// based on rc-resize-observer 0.1.3
 | 
						|
import ResizeObserver from 'resize-observer-polyfill';
 | 
						|
import { defineComponent } from 'vue';
 | 
						|
import BaseMixin from '../_util/BaseMixin';
 | 
						|
import { findDOMNode } from '../_util/props-util';
 | 
						|
 | 
						|
// Still need to be compatible with React 15, we use class component here
 | 
						|
const VueResizeObserver = defineComponent({
 | 
						|
  name: 'ResizeObserver',
 | 
						|
  mixins: [BaseMixin],
 | 
						|
  props: {
 | 
						|
    disabled: Boolean,
 | 
						|
    onResize: Function,
 | 
						|
  },
 | 
						|
  data() {
 | 
						|
    this.currentElement = null;
 | 
						|
    this.resizeObserver = null;
 | 
						|
    return {
 | 
						|
      width: 0,
 | 
						|
      height: 0,
 | 
						|
    };
 | 
						|
  },
 | 
						|
 | 
						|
  mounted() {
 | 
						|
    this.onComponentUpdated();
 | 
						|
  },
 | 
						|
 | 
						|
  updated() {
 | 
						|
    this.onComponentUpdated();
 | 
						|
  },
 | 
						|
  beforeUnmount() {
 | 
						|
    this.destroyObserver();
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
    onComponentUpdated() {
 | 
						|
      const { disabled } = this.$props;
 | 
						|
 | 
						|
      // Unregister if disabled
 | 
						|
      if (disabled) {
 | 
						|
        this.destroyObserver();
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      // Unregister if element changed
 | 
						|
      const element = findDOMNode(this);
 | 
						|
      const elementChanged = element !== this.currentElement;
 | 
						|
      if (elementChanged) {
 | 
						|
        this.destroyObserver();
 | 
						|
        this.currentElement = element;
 | 
						|
      }
 | 
						|
 | 
						|
      if (!this.resizeObserver && element) {
 | 
						|
        this.resizeObserver = new ResizeObserver(this.handleResize);
 | 
						|
        this.resizeObserver.observe(element);
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    handleResize(entries) {
 | 
						|
      const { target } = entries[0];
 | 
						|
      const { width, height } = target.getBoundingClientRect();
 | 
						|
      /**
 | 
						|
       * 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 (this.width !== fixedWidth || this.height !== fixedHeight) {
 | 
						|
        const size = { width: fixedWidth, height: fixedHeight };
 | 
						|
        this.width = fixedWidth;
 | 
						|
        this.height = fixedHeight;
 | 
						|
        this.__emit('resize', size);
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    destroyObserver() {
 | 
						|
      if (this.resizeObserver) {
 | 
						|
        this.resizeObserver.disconnect();
 | 
						|
        this.resizeObserver = null;
 | 
						|
      }
 | 
						|
    },
 | 
						|
  },
 | 
						|
 | 
						|
  render() {
 | 
						|
    return this.$slots.default?.()[0];
 | 
						|
  },
 | 
						|
});
 | 
						|
 | 
						|
export default VueResizeObserver;
 |