- 近期在项目开发中遇到了一个需要进行数据展示的图表需求,正好项目中使用的是Vue+ElementUI开发,想着图省事,决定对ElementUI中的Carousel组件进行二次封装,使其更便于项目开发使用,过程略有曲折,于是便将其记录下来防止以后忘记。
-
效果样式图
- 效果略简陋,不过这不是什么大问题,所需要的样式后期调整即可,问题在于如何实现跑马灯与Echarts图表的封装,我所希望实现的效果是,仅需要在Html结构中准备好一个容器,然后在调用组件的时候传入需要的图表具体数据,不论有多少个图表,都可以自动生成并且实现页面响应式
-
思路:
ElementUI中准备好的Carousel组件本身就已经非常好用,我们需要做的只是在自己封装的组件中,使用传进来的参数代替原本v-for生成的dom元素即可,这点也不难,使用props进行父传子就可以了。 -
实现:
-
<template> <div class="testEcharts"> <div class="refreshEcharts" v-if="isShow" :key="isShowKey"> <el-carousel class="myCarousel" ref="EcartsDis"> <el-carousel-item v-for="item, index in echartsShowData" :key="item.id" class="myCarouselItem"> <div :id="'echarts' + index" class="com"></div> </el-carousel-item> </el-carousel> </div> </div> </template>
template部分
-
除却最外层的testEcharts外,我还包裹了一层refreshEcharts,这一层的样式设置与最外层一致,都是仅仅设置其大小为HTML中准备好的容器的大小,但是如果不加入这一层嵌套,则在后续使用v-for进行渲染时会出现数据更新但是视图并不更新的情况(v-for并没有实现双向绑定)。而其中绑定了一个key属性,这是为了在v-if为false时,真正的彻底从内存中销毁该dom元素(v-if在设计时为了性能考虑,还在内部维护了一个缓存,将v-if为false的组件存储在内存中,当v-if的条件重新变为true时,对其进行对比,如果发现和false之前一致时,则将其直接渲染出来而非重新创建)
-
-
<script> /* 该组件封装的目的是实现Echarts图和Carousel轮播图组件的结合使用 需要传入props值为: ehcartsData=>包含该图表的所有配置项 */ export default { name: 'myCarousel', data() { return { echartsShowData: [], isShow: true, isShowKey: 1 } }, props: { ehcartsData: {} }, watch: { ehcartsData(newVal) { // 将其外部包裹的元素使用v-if进行销毁 // 流程为:销毁-》修改key值-》内存判断不同-》彻底销毁-》重构 this.isShow = false this.isShowKey += 1 if (true) { this.$nextTick(() => { this.isShow = true this.echartsShowData = newVal this.getEcharts(this.echartsShowData) }) } } }, methods: { getEcharts(Edata) { console.log('Edata.length=' + Edata.length) if (Edata.length != 0) // 等待dom元素全部加载完成后再进行Echarts图表的绘制 this.$nextTick(() => { Edata.forEach((element, index) => { // let myCarouselName = `myChart${index}` console.log(`id=echarts${index}`) let myChartName = this.$echarts.init(document.getElementById(`echarts${index}`)); console.log('myChartName=' + myChartName) myChartName.setOption(element) // 给Echarts图表实例添加响应式 this.$nextTick(() => { window.addEventListener("resize", () => { myChartName.resize(); }); }) }); }) else console.warn('init中') } }, } </script>
script部分
-
需要注意的点是在父组件中的echartsData改变时,将外层判断是否展示的v-if值设置为false,然后使其key值自增,并且在该元素的v-if=false的操作完成后,再将其设置为=true,即文中的this.$nextTick()钩子函数中修改,修改完成之后再调用自定义的生成Ecarts图方法getEcharts()进行图表的生成。在定义的方法中也需要使用this.$nextTick()钩子,否则会报无法找到DOM元素的错误(即一定要确保其有dom元素,再去寻找),最下面的一个this.nextTick()同理,一定是已经有了元素,再去设置图表响应式。
-
-
<style scoped> .testEcharts { width: 100%; height: 100%; } .refreshEcharts{ width: 100%; height: 100%; } .myCarousel { width: 100%; height: 100%; } .myCarouselItem { width: 100%; height: 100%; } /deep/.el-carousel__container { width: 100%; height: 100%; } .com { width: 100% !important; height: 100% !important; } </style>
css部分
-
没什么好说的,就是全部设置为最外层准备好的容器大小即可,这样调整的时候只需要调整最外层的容器即可.
-
-
输入数据
一种ElementUI+Echarts+Vue的跑马灯数据图表思路
于 2023-12-03 01:24:09 首次发布