2020-03-07 19:45:13 +08:00
|
|
|
// based on rc-resize-observer 0.1.3
|
|
|
|
import ResizeObserver from 'resize-observer-polyfill';
|
|
|
|
|
|
|
|
// Still need to be compatible with React 15, we use class component here
|
|
|
|
const VueResizeObserver = {
|
|
|
|
name: 'ResizeObserver',
|
|
|
|
props: {
|
|
|
|
disabled: Boolean,
|
|
|
|
},
|
|
|
|
data() {
|
|
|
|
this.currentElement = null;
|
|
|
|
this.resizeObserver = null;
|
|
|
|
return {
|
|
|
|
width: 0,
|
|
|
|
height: 0,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
mounted() {
|
|
|
|
this.onComponentUpdated();
|
|
|
|
},
|
|
|
|
|
|
|
|
updated() {
|
|
|
|
this.onComponentUpdated();
|
|
|
|
},
|
2020-06-11 16:13:09 +08:00
|
|
|
beforeUnmount() {
|
2020-03-07 19:45:13 +08:00
|
|
|
this.destroyObserver();
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
onComponentUpdated() {
|
|
|
|
const { disabled } = this.$props;
|
|
|
|
|
|
|
|
// Unregister if disabled
|
|
|
|
if (disabled) {
|
|
|
|
this.destroyObserver();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unregister if element changed
|
|
|
|
const element = this.$el;
|
|
|
|
const elementChanged = element !== this.currentElement;
|
|
|
|
if (elementChanged) {
|
|
|
|
this.destroyObserver();
|
|
|
|
this.currentElement = element;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.resizeObserver && element) {
|
|
|
|
this.resizeObserver = new ResizeObserver(this.onResize);
|
|
|
|
this.resizeObserver.observe(element);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onResize(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.fixedHeight = fixedHeight;
|
|
|
|
this.$emit('resize', size);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
destroyObserver() {
|
|
|
|
if (this.resizeObserver) {
|
|
|
|
this.resizeObserver.disconnect();
|
|
|
|
this.resizeObserver = null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
render() {
|
2020-06-03 18:36:18 +08:00
|
|
|
return this.$slots.default && this.$slots.default()[0];
|
2020-03-07 19:45:13 +08:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
export default VueResizeObserver;
|