1. 版本介绍
前端框架:vue("v 3.2.38”),绘图:echarts("v 5.3.3”) vue2和vue3语法上会有些不同,Echarts版本影响不大
2. 遇到问题
2.1、页面大小变化时,画布大小未随页面大小变化
2.2、配合tab页使用时,切换tab,数据改变后,重新切换到图形tab会报获取不到dom宽高如下警告:
3. 问题解决(实测有效)
3.1、解决页面大小变化时,画布大小未随页面大小变化问题
主要解决思路: 当window变化resize时,画布大小也跟随变化resize: vue执行mounted生命周期时,为window绑定resize事件,vue执行beforeUnmount生命周期时window解绑resize事件。代码如下: util.js文件
export const on = (function () {
if (document.addEventListener) {
return function (element, event, handler) {
if (element && event && handler) {
element.addEventListener(event, handler, false)
}
}
} else {
return function (element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler)
}
}
}
})()
export const off = (function () {
if (document.removeEventListener) {
return function (element, event, handler) {
if (element && event) {
element.removeEventListener(event, handler, false)
}
}
} else {
return function (element, event, handler) {
if (element && event) {
element.detachEvent('on' + event, handler)
}
}
}
})()
chart.vue
<template>
<div ref="dom" style="height:600px;width:600px;"></div>
</template>
<script>
import * as echarts from "echarts";
import { on, off } from "../../../../libs/util.js";
export default {
name: "LineChart",
data() {
return {
dom: null,
};
},
methods: {
resize() {
this.dom.resize();
},
drawLine() {
if(this.dom){
this.dom.dispose()
}
this.dom = echarts.init(this.$refs.dom);
let option = {
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'
}
]
};
}
this.dom.setOption(option, true);
},
},
mounted() {
this.drawLine();
on(window, "resize", this.resize);
},
beforeUnmount() {
off(window, "resize", this.resize);
},
};
</script>
<style scoped>
</style>
3.2、解决tab页切换时,vue警告不能获取绘图dom宽高问题
我是把绘图部分抽出来了,作为一个单独的组件 (如果只放在一个vue组件里,应该不会存在这个问题),父组件调用接口获取数据,将数据传给子组件,子组件监听数据发生变化时执行绘图函数,因为tab页是点击当前tab才会加载dom,所以在另一个tab页数据发生变化时,绘图组件监听到数据变化会执行绘图函数,但此时dom还未加载,所以获取不到宽高,所以会报相关警告,我们会看到一个空页面。 主要解决思路: 除了监听数据变化重新绘制图形外,监听tab页更改并当前tab页为绘制图形tab页时,dom已经加载,此时执行绘制图形函数就能正常绘制出图形。相关代码如下: parent.vue(一个查询框和一个tab页,查询框更新数据,tab页展示数据)
<template>
<div style="height:100%;width:100%;">
<Card dis-hover>
<Form
ref="searchForm"
:model="searchForm"
label-position="right"
:label-width="60"
>
<Row :gutter="24">
<Col span="8">
<FormItem label="name" prop="name">
<Input
v-model="searchForm.name"
placeholder="请输入name"
clearable
/>
</FormItem>
</Col>
<Col span="8">
<FormItem>
<div>
<Button type="primary" @click="search">查询</Button>
<Button class="ml15" @click="clear" style="marginLeft: 10px"
>清空</Button
>
</div>
</FormItem>
</Col>
</Row>
</Form>
</Card>
<Tabs :animated="false" style="marginTop:20px;" v-model="tab" @on-click="changeTabs">
<TabPane name="chart" label="图形" icon="md-analytics">
<Tree class="chart" :value="chartData" :name="searchForm.name" :tab="tab"/>
</TabPane>
<TabPane name="table" label="表格" icon="md-document">
<Table class="table" :tableData="tableData" :name="searchForm.name" :loading="loading"/>
</TabPane>
</Tabs>
</div>
</template>
<script>
import Table from './table.vue'
import Tree from './components/charts/tree.vue'
import {searchData} from '@/api/searchData.js'
export default {
name: 'Parent',
components: {
Table,
Chart
},
data(){
return {
searchForm: {
name: "",
},
loading: false,
tab: 'chart',
chartData: {},
tableData: [],
}
},
mounted(){
this.getData()
},
methods: {
search() {
this.getData();
},
clear() {
this.$refs.searchForm.resetFields();
},
changeTabs(tab){
this.tab = tab
},
async getData() {
try{
const params = {
nmae: this.searchForm.name
}
this.loading = true
const {data:json}= await searchData(params)
this.chartData = {}
this.tableData = []
if(json.success){
this.chartData = json.data
this.tableData.push(json.data)
this.$Message.success("成功")
this.loading = false
}else{
this.chartData = {}
this.tableData = []
this.$Message.error("失败")
}
}catch(error){
console.log(error)
}
},
}
}
</script>
<style scoped>
.chart{
height: 680px;
overflow: auto;
}
.table{
height: 650px;
overflow: auto;
}
</style>
tree.vue(table.vue就是普通的表格组件,这里不再放出代码,主要看下Echarts绘图部分代码)
<template>
<div style="height:100%;width:100%">
<div ref="dom" style="height: 680px"></div>
</div>
</template>
<script>
import * as echarts from "echarts";
import { on, off } from "../../../../libs/util.js";
export default {
name: "Tree",
components: {
},
props: {
value: Object,
name: String,
tab: String,
},
data() {
return {
showDetail: false,
dom: null,
detailData: {},
treeData: [],
};
},
methods: {
resize() {
this.dom.resize();
},
renderChart() {
if (this.dom) {
this.dom.dispose();
}
var option;
this.dom = echarts.init(this.$refs.dom);
option = {
tooltip: {
trigger: "item",
triggerOn: "mousemove",
formatter: (data) => {
return `name: ${data.data.name} <br/> age: ${data.data.age}`;
},
},
series: [
{
type: "tree",
id: 0,
zoom: 0.8,
roam: true,
name: "tree1",
data: [this.value],
top: "20px",
left: "180px",
bottom: "20px",
right: "200px",
symbol: "emptyCircle",
symbolSize: 10,
edgeShape: "polyline",
edgeForkPosition: "40%",
initialTreeDepth: 3,
label: {
position: "left",
verticalAlign: "middle",
align: "right",
color: "#293c55",
margin: [4, 4],
borderWidth: 1,
borderColor: "#aaa",
backgroundColor: "white",
borderRadius: 2,
padding: [5, 4],
formatter: (data) => {
if (data.data) {
return (
[
`{name|${data.data.name}}`,
`{age|${
data.data.age.}}`,
].join("\n") + ` {favor|${data.data.favor}}`
);
},
rich: {
name: {
color: "#5E6472",
fontSize: "12",
lineHeight: 20,
align: "left",
},
age: {
color: "#5E6472",
fontSize: "12",
lineHeight: 20,
align: "left",
},
favor: {
color: "white",
backgroundColor: "#DD1C1A",
padding: 5,
margin: 5,
borderRadius: 3,
align: "right",
},
},
},
leaves: {
label: {
position: "right",
verticalAlign: "middle",
align: "left",
},
},
emphasis: {
focus: "relative",
},
expandAndCollapse: true,
animationDuration: 550,
animationDurationUpdate: 750,
},
],
};
this.dom.setOption(option, true);
if (option && typeof option === "object") {
this.dom.setOption(option, true);
this.dom.on("mousedown", (e) => {
const flag = e.event.target.__proto__.constructor.name;
if (flag == "Rect" || flag == "TSpan") {
this.showDetail = true;
this.detailData = e.data;
} else if (flag == "Sub") {
}
});
}
},
},
mounted() {
this.$nextTick(() => {
this.renderChart();
on(window, "resize", this.resize);
});
},
beforeUnmount() {
off(window, "resize", this.resize);
},
watch: {
value: {
handler() {
this.$nextTick(() => {
this.renderChart();
});
},
deep: true,
},
tab: {
handler(){
if(this.tab == 'chart'){
this.$nextTick(() => {
this.renderChart()
})
}
}
}
},
};
</script>
<style scoped></style>
4、主要代码截图(代码太长可以跳过只看关键代码截图,有疑惑再看3主要解决方案完整代码)
4.1、画布不随页面变化问题解决关键代码
util.js文件里绑定事件和解绑事件 组件相关代码截图:
4.2、tab页echarts绘图获取不到dom宽高问题解决关键代码
|