Vue自定义指令v-show-chart暂无数据时显示文本或者自定义组件(echart版)

1,011 阅读1分钟

由于需求,要在制作的图表没有数据的时候,显示暂无数据或者自定义的组件,我深知我赋予的责任,我不下地狱,谁下地狱,我主动表示,我做不动

老板:这里你说的算吗?既然你都这么说了,我看与你有缘,就你来吧

当时我的内心畅想起了大悲咒

没办法,既然要做,咱也不能一个一个不是,今天教大家如何用vue的自定义指令directives来骚一把 我这里用了一种比较巧妙的方法,因为echarts在执行init方法绘制图表时,会在挂载div上添加一个_echarts_instance_属性,我利用了MutationObserver监听属性变化,当echarts添加属性时,MutationObserver监听到属性变化并执行定义的回调函数,回调中我会判断是否存在可以绘制图表的数据,没有的话我就会删除子节点和_echarts_instance_属性并把自定义的组件或文本appendChild添加上去

function judgeValueToString (value, type) {
  return Object.prototype.toString.call(value) === `[object ${type}]`;
}

function isArray (value) {
  return judgeValueToString(value, 'Array');
}

function updateDom (el, echartInstance, text) {
  let hasData = false;
  let series = echartInstance.getOption().series;
  series = isArray(series) ? series : [series];
  series.forEach(({ data }) => {
    if (data.length) hasData = true;
  });
  if (!hasData) {
    // while (el.firstChild) el.removeChild(el.firstChild);
    el.innerHTML = null;
    el.removeAttribute('_echarts_instance_');
    const instance = new (Vue.extend(NoData))({
      propsData: {
        text
      }
    });
    el.appendChild(instance.$mount().$el);
  }
}

export default {
  install (Vue, opt) {
    const { text } = opt || {};
    // 监听数据指令,如果没有数据替换图表为其他页面
    Vue.directive('show-chart', {
      bind (el) {
          const observer = new MutationObserver(() => {
            const echartInstance = echarts.getInstanceByDom(el);
            if (echartInstance) {
              const setOption = echartInstance.setOption.bind(echartInstance);
              const updateDom = () => echartUpdateDom(el, echartInstance, text);
              Object.defineProperty(echartInstance, 'setOption', {
                value (option, notMerge, lazyUpdate) {
                  // 异步更新可以获取到最新的option
                  nextTick(updateDom);
                  setOption(option, notMerge, lazyUpdate);
                }
              });
            }
          });
          observer.observe(el, { attributes: true });
        }
    });
  }
};

自定义的组件,将会在无数据时显示

<!-- 空数据显示内容 -->
<template>
  <div class="echart-no-data">{{text}}</div>
</template>

<script>
export default {
  name: 'echartNoData',
  props: {
    text: String
  },
  data () {
    return {
    };
  }
};

</script>
<style lang='less' scoped>
.echart-no-data {
  height: 100%;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>

这个插件最后在入口Vue实例挂载之前通过Vue.use安装就可以了

import noData from './plugins/no_data';
Vue.use(noData);

源代码地址

喜欢这篇文章并且长得好看的人都点赞收藏了,你还等什么