学习目标:
实现 echart 表在网页中的可拖拽式布局+自适应大小
学习内容:
- 安装 vue-grid-layout
- 安装 echart
- 编写一个 echart 折线图组件
- 设置 echart 自适应大小
一、安装 echart
-
切到 vue-cli 目录下执行一下命令
此命令将为为你在本项目下安装 vue-grid-layout
npm install vue-grid-layout --save
-
编写放置 vue-grid-layout 的组件
引入 vue-grid-layout 的两个组件 GridLayout, GridItem 并注册
<script> import { GridLayout, GridItem } from "vue-grid-layout" //引入组件 export default { name: 'VueGirdLayout', components:{ //注册组件 GridLayout, GridItem } } </script>
在页面上放入组件
<template> <div> <h1>vue-grid-layout可拖拽式布局</h1> <grid-layout :layout.sync="layout" :col-num="12" :row-height="30" :is-draggable="draggable" :is-resizable="resizable" :vertical-compact="true" :use-css-transforms="true" > <grid-item v-for="item in layout" :static="item.static" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i" :key="item.i" > <span class="text">{ { item.i}}</span> </grid-item> </grid-layout> </div> </template> <script> import { GridLayout, GridItem } from "vue-grid-layout" //引入组件 export default { name: 'VueGirdLayout', //注册组件 components:{ GridLayout, GridItem }, data() { return { layout: [ //每一个 grid-item 的属性 { "x":0,"y":0,"w":4,"h":4,"i":"0", static: false}, { "x":2,"y":0,"w":5,"h":5,"i":"1", static: false}, { "x":4,"y":0,"w":6,"h":6,"i":"2", static: false}, ], draggable: true, //是否可拖拽 resizable: true, //是否可更改大小 } }, } </script> <style> .vue-grid-layout { background: #eee; } .vue-grid-item:not(.vue-grid-placeholder) { background: rgb(255, 255, 255); border: 1px solid black; } .vue-grid-item .static { background: #cce; } </style>
layout 数组的数据为 GridItem 组件的属性
“x”、"y"表示为 GridItem 组件的坐标,“w”、“h” 表示为 GridItem 组件的宽和高,"i"表示为 GridItem 组件的id,“static” 表示为单个 GridItem 组件是否可被拖拽。此时该组件的页面应该为下图所示
二、安装echart
-
在 vue-cli 目录下执行以下命令
此命令在此项目下安装 echart
npm install echarts --save
-
引入 echart
我们仅需要在使用到 echart 图的的组件中引用 echart
创建一个折线图组件 LineChart.vue<template> </template> <script> import * as echarts from 'echarts' //引入图标 export default { name:'LineChart' //命名组件 } </script> <style> </style>
三、编写 echart 折线图组件
-
写入一个折线图
<template> <div ref="MyChartDom" :style="{width: '100%', height: '100%'}"></div> </template> <script> import * as echarts from 'echarts' //引入图标 export default { name:'LineChart', //命名组件 data() { return { option:{ //创建折线图的配置项数据 xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [ { data: [150, 230, 224, 218, 135, 147, 260], type: 'line' } ] }, ChartDom:null, MyChart:null } }, methods: { CreateChart(){ this.ChartDom = this.$refs.MyChartDom // 获取到你防止echart的Dom this.MyChart = echarts.init(this.ChartDom) // 实例化你的 echart 图 this.MyChart.setOption(this.option) setTimeout (()=>{ //由于网格布局拖拽放大缩小图表不能自适应,这里设置一个定时器使得echart加载为一个异步过程 this.$nextTick(() => { this.MyChart.resize() }) },0) } }, mounted() { // 页面初始化后执行 this.CreateChart() }, } </script> <style> </style>
-
将在之前创建的 vue-grid-layout 中引用刚刚写的折线图组件
引入折线图组件
import LineChart from "./LineChart.vue"
注册折线图组件
components:{ GridLayout, GridItem, LineChart },
引用折线图组件
将 grid-item 标签下的 span 标签替换为折线图组件
<template> <div> <h1>vue-grid-layout可拖拽式布局</h1> <grid-layout :layout.sync="layout" :col-num="12" :row-height="30" :is-draggable="draggable" :is-resizable="resizable" :vertical-compact="true" :use-css-transforms="true" > <grid-item v-for="item in layout" :static="item.static" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i" :key="item.i" > <LineChart/> </grid-item> </grid-layout> </div> </template>
此时页面应该为如下图所示
-
echart 不能自适应大小
四、设置 echart 自适应大小
我们的思路是在 echart 组件中创建一个调整大小的函数,每当 vue-grid-layout 组件中的 grid-item 大小改变时调用 echart 组件的函数。
-
在 echart 组件中编写调节 echart 大小的函数
在echart 组件中 methods 中创建一个 sizechange() 函数
methods: { CreateChart(){ this.ChartDom = this.$refs.MyChartDom // 获取到你防止echart的Dom this.MyChart = echarts.init(this.ChartDom) // 实例化你的 echart 图 this.MyChart.setOption(this.option) setTimeout (()=>{ //由于网格布局拖拽放大缩小图表不能自适应,这里设置一个定时器使得echart加载为一个异步过程 this.$nextTick(() => { this.MyChart.resize() }) },0) }, sizechange(){ // 修改 echart 大小 this.MyChart.resize() } }
-
在 vue-grid-layout 组件中当改变 grid-item 大小时调用 echart 组件的sizechange()函数
在父组件中的 grid-item 设定当大小改变时执行某个函数
<template> <div> <h1>vue-grid-layout可拖拽式布局</h1> <grid-layout :layout.sync="layout" :col-num="12" :row-height="30" :is-draggable="draggable" :is-resizable="resizable" :vertical-compact="true" :use-css-transforms="true" > <grid-item v-for="item in layout" :static="item.static" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i" :key="item.i" @resize="SizeAutoChange(item.i)" > <!-- 当 grid-item 改变时执行 SizeAutoChange() 函数 --> <LineChart :ref="`LineChart${item.i}`"/> <!-- 设定好 ref 使得下面操控的是某个子组件的函数 --> </grid-item> </grid-layout> </div> </template>
在父组件中创建一个函数调用子组件 的函数SizeAutoChange()
methods: { SizeAutoChange(ChartId){ var EchartId = `LineChart${ ChartId}` // 拿到子组件实力对象 eval(`this.$refs.${ EchartId}[0].sizechange()`) //执行子组件的函数 } }
此时折线图就可以根据 grid-item 拖拽后的大小进行自适应了
chart 根据父元素自适应大小
完整代码
父组件 VueGirdLayout.vue 部分
<template>
<div>
<h1>vue-grid-layout可拖拽式布局</h1>
<grid-layout :layout.sync="layout"
:col-num="12"
:row-height="30"
:is-draggable="draggable"
:is-resizable="resizable"
:vertical-compact="true"
:use-css-transforms="true"
>
<grid-item v-for="item in layout"
:static="item.static"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.i"
:key="item.i"
@resize="SizeAutoChange(item.i)"
> <!-- 当 grid-item 改变时执行 SizeAutoChange() 函数 -->
<LineChart :ref="`LineChart${item.i}`"/> <!-- 设定好 ref 使得下面操控的是某个子组件的函数 -->
</grid-item>
</grid-layout>
</div>
</template>
<script>
import {
GridLayout, GridItem } from "vue-grid-layout" //引入组件
import LineChart from "./LineChart.vue"
export default {
name: 'VueGirdLayout', //注册组件
components:{
GridLayout,
GridItem,
LineChart
},
data() {
return {
layout: [ //每一个 grid-item 的属性
{
"x":0,"y":0,"w":4,"h":4,"i":"0", static: false},
{
"x":2,"y":0,"w":5,"h":5,"i":"1", static: false},
{
"x":4,"y":0,"w":6,"h":6,"i":"2", static: false},
],
draggable: true, //是否可拖拽
resizable: true, //是否可更改大小
}
},
methods: {
SizeAutoChange(ChartId){
var EchartId = `LineChart${
ChartId}` // 拿到子组件实力对象
eval(`this.$refs.${
EchartId}[0].sizechange()`) //执行子组件的函数
}
},
}
</script>
<style>
.vue-grid-layout {
background: #eee;
}
.vue-grid-item:not(.vue-grid-placeholder) {
background: rgb(255, 255, 255);
border: 1px solid black;
}
.vue-grid-item .static {
background: #cce;
}
</style>
子组件 LineChart.vue 部分
<template>
<div @click="sizechange" ref="MyChartDom" :style="{width: '100%', height: '100%'}"></div>
</template>
<script>
import * as echarts from 'echarts' //引入图标
export default {
name:'LineChart', //命名组件
data() {
return {
option:{
//创建折线图的配置项数据
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
]
},
ChartDom:null,
MyChart:null
}
},
methods: {
CreateChart(){
this.ChartDom = this.$refs.MyChartDom // 获取到你防止echart的Dom
this.MyChart = echarts.init(this.ChartDom) // 实例化你的 echart 图
this.MyChart.setOption(this.option)
setTimeout (()=>{
//由于网格布局拖拽放大缩小图表不能自适应,这里设置一个定时器使得echart加载为一个异步过程
this.$nextTick(() => {
this.MyChart.resize()
})
},0)
},
sizechange(){
// 修改 echart 大小
this.MyChart.resize()
}
},
mounted() {
// 页面初始化后执行
this.CreateChart()
}
}
</script>
<style>
</style>