遇到这么一个需求,如下图所示有很多图表组件,要能通过右上角按钮切换一行显示几个图表,图表块还要能拖拽、排序,一番摸索后记录一下实现思路。
1、首先,布局切换打算使用grid布局来实现,[具体可以看我另一篇文章](使用grid布局实现页面布局切换 - 掘金 (juejin.cn))
2、拖拽元素,选择之前使用过的 vuedraggable 插件实现,拖拽后数据对象排序也实时变化。
vue.draggable.next是vue.draggable的vue3版本,使用文档如下
[中文文档](https://www.itxst.com/vue-draggable-next/tutorial.html)
[gihub](https://github.com/SortableJS/vue.draggable.next)
3、因为要记录拖拽排序的顺序,所以组件不可能一个个写在模板里,得配合 第2 里的拖拽插件,根据数据来动态渲染显示那个组件,所以就用到了vue中的动态组件
<component :is="currentTab"></component>
通过数据记录组件的名称,通过vuedraggable渲染动态组件,并实现拖动
代码如下
<template>
<div class="test">
<!-- 顶部按钮 -->
<div class="button-block">
<el-radio-group v-model="radio" size="large">
<el-radio-button label="1">
<span class="iconfont icon-shuang"></span
></el-radio-button>
<el-radio-button label="2">
<span class="iconfont icon-san"></span
></el-radio-button>
</el-radio-group>
</div>
<!-- 可拖拽插件 通过class控制grid属性,切换布局 -->
<draggable
v-model="myArray"
item-key="id"
@end="onEnd"
class="content"
:class="{ grid2: radio == '1', grid4: radio == '2' }"
>
<!-- is匹配到的组件名,即会渲染该组件 -->
<template #item="{ element }">
<component :is="element.comp"></component>
</template>
</draggable>
</div>
</template>
<script>
import draggable from "vuedraggable";
// 引入组件
import Comp1 from "./comp/comp1.vue";
import Comp2 from "./comp/comp2.vue";
import Comp3 from "./comp/comp3.vue";
export default {
components: {
draggable,
// 注册组件
Comp1,
Comp2,
Comp3,
},
data() {
return {
radio: "1",
// 保存了组件名的数据
myArray: [
{ name: "11", id: 0, comp: "comp1" },
{ name: "22", id: 1, comp: "comp3" },
{ name: "33", id: 2, comp: "comp2" },
{ name: "44", id: 3, comp: "comp2" },
{ name: "55", id: 4, comp: "comp1" },
{ name: "66", id: 5, comp: "comp3" },
{ name: "66", id: 6, comp: "comp2" },
],
};
},
watch: {
radio(val) {
console.log(val);
},
},
methods: {
// vuedraggable 拖拽结束事件处罚方法
onEnd() {
console.log(this.myArray);
},
},
};
</script>
<style lang="scss" scoped>
.test {
.button-block {
text-align: center;
}
.content {
margin-top: 20px;
display: grid;
grid-gap: 16px;
}
}
// 不同布局样式
.grid2 {
grid-template-columns: repeat(2, 1fr);
}
.grid4 {
grid-template-columns: repeat(4, 1fr);
}
</style>
组件内
// 组件1
<template>
<div class="comp1">comp1</div>
</template>
<style lang="scss" scoped>
.comp1 {
height: 100px;
background-color: #f82a42;
border-radius: 8px;
}
</style>
实现效果
一行2个布局
一行4个布局
拖拽前数组排序
拖拽后数组排序
4、最后
在上述基础上,最开始的需求中,将按钮绑定的值保存在vuex(或pinia中),在各个组件中监听值的变化,布局切换后,
组件中使用echarts.resize()重新渲染图表即完成。