菜单栏缩放展开和页面全屏时不刷新页面重新渲染(适配不同浏览器)
获取祖先盒子的宽度,监听祖父元素的宽度,只有宽度变化时才重新挂载
ResizeObserver
是原生 JavaScript 提供的 API,用来监听一个 DOM 元素 尺寸的变化(宽度、高度)。与
window.onresize
不同,它可以监听具体某个元素,而不仅仅是整个浏览器窗口。data(){
showChart: true,
prevWidth: 0
},
mounted() {
const el = this.$refs.dashboard;
if (el) {
this.prevWidth = el.offsetWidth; // 初始化宽度
// 创建 ResizeObserver 实例
this.resizeObserver = new ResizeObserver((entries) => { //entries 是一个数组,包含了所有发生变化的元素的尺寸信息对象
const newWidth = entries[0].contentRect.width;
if (newWidth !== this.prevWidth) { // 只有宽度变化时才重新挂载
// console.log('宽度从', this.prevWidth, '变为', newWidth);
this.prevWidth = newWidth;
this.remountChart(); // 宽度变化时重新挂载组件
}
});
// 开始监听
this.resizeObserver.observe(el);
}
宽度变化时重新挂载组件,通过v-if来控制盒子或组件Dom元素销毁和创建,通过this.$nextTick()等 DOM 更新完成之后,再把
showChart
设置为 true
,防止组件不刷新remountChart() {
this.showChart = false;
this.$nextTick(() => {
this.showChart = true;
});
}
附加功能:全屏效果
适配常见浏览器并更新
handleFull() {
const elem = this.$refs.dashboard; // 这里是整个页面的根元素
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.mozRequestFullScreen) { // Firefox
elem.mozRequestFullScreen();
} else if (elem.webkitRequestFullscreen) { // Chrome, Safari 和 Opera
elem.webkitRequestFullscreen();
} else if (elem.msRequestFullscreen) { // IE/Edge
elem.msRequestFullscreen();
}
this.remountChart()
},
考虑到:菜单栏缩放展开和全屏时会触发多次监听,频繁的
remountChart()
导致性能下降,采用防抖来处理。并在组件销毁时清理监听,防止内存泄漏。const el = this.$refs.dashboard;
if (el) {
this.prevWidth = el.offsetWidth; // 初始化宽度
// 创建 ResizeObserver 实例
// 尺寸变化回调(带防抖)
const handleResize = this.debounce((entries) => {
const newWidth = entries[0].contentRect.width;
if (newWidth !== this.prevWidth) {
console.log('宽度从', this.prevWidth, '变为', newWidth);
this.prevWidth = newWidth;
this.remountChart(); // 重新挂载图表组件
}
}, 200);
// 创建 ResizeObserver 实例
this.resizeObserver = new ResizeObserver(handleResize);
// 开始监听
this.resizeObserver.observe(el);
}
防抖函数
debounce(fn, delay) {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
},
清理监听
beforeDestroy() {
// 清理监听
this.resizeObserver && this.resizeObserver.disconnect();
this.resizeObserver = null;
window.removeEventListener('resize', this.onResize);
},