首页 前端知识 vue3解决侧边栏菜单折叠/展开,echarts的resize方法不生效问题

vue3解决侧边栏菜单折叠/展开,echarts的resize方法不生效问题

2024-09-04 23:09:43 前端知识 前端哥 253 537 我要收藏

希望大家应该也遇到过,当我们使用echarts时,在侧边导航折叠展开时,resize方法不生效的问题。以下提供两种个人比较推荐的解决方法。

方法一

使用 setTimeout

可以看到elementui的过渡时间是0.3s
在这里插入图片描述
所以在监听侧边栏折叠的时间使用settimeout,0.3s后执行resize方法。

watch(() => hasCollapse.value, (val) => {
   setTimeout(() => {
     chart.value?.resize();
   }, 300);
 })

方法二(推荐)

编写动画函数执行resize方法

// animation.ts
export const useAnimation = (
  duration: number, 
  from: number, 
  to: number, 
  callback: (value: number) => void
) => {
  const startTime = Date.now();
  const diff: number = to - from;
  const average: number = diff / duration;
  let value: number = from;
  callback(value);
  const _animate = () => {
    const currentTime: number = Date.now();
    const timeDiff: number = currentTime - startTime;
    if (timeDiff >= duration) {
      value = to;
      callback(value);
      return;
    }
    value = diff < 0 ? from + (timeDiff * average) : timeDiff * average;
    callback(value);
    requestAnimationFrame(_animate);
  }
  _animate();
}

注意:需要结合自定义hook,可以封装一个hook,返回容器的宽(window.innerWidth - 侧边导航菜单的宽度),这里我侧边菜单的宽度是 200(展开状态)和 60(折叠状态)

// useContainer.ts
import { computed, ref, watch } from "vue";
import { useSettingStore } from "@/store";
import { useEventListener } from "./event";
const settingStore = useSettingStore();
// 获取主体内容的宽高
export const useWidthHeight = () => {
  const hasCollapse = computed<boolean>(() => {
    return settingStore.hasCollapse;
  })
  // 高度:window.innerHeight - header 高度
  const mainHeight = ref<number>(window.innerHeight - 60);
  // 宽度:window.innnerWidth - aside 宽度
  const mainWidth = ref<number>(window.innerWidth - (hasCollapse.value ? 60 : 200));
  const updateWidthHeight = () => {
    mainHeight.value = window.innerHeight - 60;
    mainWidth.value = window.innerWidth - (hasCollapse.value ? 60 : 200);
  }
  // 挂载/销毁事件,注:useEventListener是我封装的hooks,这里跟 window.addEventListener('resize')是一样的
  useEventListener(window, 'resize', updateWidthHeight);

  watch(hasCollapse, (val) => {
    updateWidthHeight();
  })
  return { height: mainHeight, width: mainWidth };
}

当监听到折叠时这个主体宽度是会变化的。
在组件中导入这两个方法

import { useAnimation } from '@/utils/animation';
import { useWidthHeight } from '@/hooks';
const { width } = useWidthHeight();
const onResize = () => {
  chart.value?.resize();
}
onMounted(() => {
  initChart();
  window.addEventListener('resize', onResize);
})
onBeforeUnmount(() => {
  window.removeEventListener('resize', onResize);
})
 // 监听主体内容宽度,传入时间300ms,宽度新/旧值,在回调函数中执行resize方法
watch(width, (nVal, oVal) => {
   // 侧边栏展开/折叠动画间隔0.3s,使用动画解决侧边栏展开/折叠resize不生效
   useAnimation(300, nVal, oVal, () => {
     chart.value?.resize();
   })
})

效果不会像使用setTimeout方法,在最后突然抖动一下去resize,这个方法可以在过渡中resize,体验相对友好。
当然useAnimation这个工具函数用途不止如此,还可以做一些其他动画过渡效果,大家可以试一试,希望对你们有用。

方法三(推荐)

使用 ResizeObserver 封装 v-resize 指令

const map = new WeakMap();
const resizeOb = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const handler = map.get(entry.target);
    let width, height;
    if (entry.borderBoxSize) {
      const contentBoxSize = Array.isArray(entry.borderBoxSize)
        ? entry.borderBoxSize[0]
        : entry.borderBoxSize;
      width = contentBoxSize.inlineSize;
      height = contentBoxSize.blockSize;
    } else {
      width = entry.contentRect.width;
      height = entry.contentRect.height;
    }
    handler({ width, height });
  }
});
/**
 * 监听元素尺寸变化
 * @example
 * ```vue
 * <div v-resize="handleResize"></div>
 * ```
 * ```js
 * const handleResize = ({ width, height }) => {
 *   // todo
 * };
 * ```
 */
const vResizeEl = {
  mounted(el, binding) {
    const value = binding.value;
    if (value && typeof value === 'function') {
      map.set(el, value);
    } else {
      throw new Error('binding value is not a function');
    }
    resizeOb.observe(el);
  },
  unmounted(el) {
    resizeOb.unobserve(el);
  },
};

export default vResizeEl;

用法

<div ref="chartInstance" v-resize="handleResize"> </div>
  // 响应图表大小
  const handleResize = () => {
    if (chartInstance.value) {
      chartInstance.value.resize();
    }
  };
转载请注明出处或者链接地址:https://www.qianduange.cn//article/17626.html
标签
评论
发布的文章

关于HTML的知识

2024-09-18 23:09:36

js简单实现轮播图效果

2024-09-18 23:09:36

CSS3美化网页元素

2024-09-18 23:09:27

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!