由于需求,要在制作的图表没有数据的时候,显示暂无数据或者自定义的组件,我深知我赋予的责任,我不下地狱,谁下地狱,我主动表示,我做不动
老板:这里你说的算吗?既然你都这么说了,我看与你有缘,就你来吧
当时我的内心畅想起了大悲咒
没办法,既然要做,咱也不能一个一个不是,今天教大家如何用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);
喜欢这篇文章并且长得好看的人都点赞收藏了,你还等什么