图表多层上下钻2:多次请求
echars官网:https://www.echartsjs.com/zh/index.html
解决简单的双层上下钻后,这次来解决更复杂的多层下钻。顾名思义,就是有很多层数据了,这时候如果还只有一个返回按钮,交互就显得很不友好。最后经过大佬同事的建议和指示,用了jquery配合面包屑导航来实现。
首先来看看效果图:


点击上方的面包屑导航就能加载对应页面的数据,这正是我们想要的效果。
首先说一下,这次后台给的数据,是要多次请求的。也就是每下钻一次,我们要请求一次。这种方法对前端来说更简单一些,数据全都是后台在处理,前端的重心只要放在处理面包屑导航上。(我后面还会写一篇处理一次性请求的多层上下钻,这个稍微麻烦一点)。接下来思路如下:
一、自定义导航div
先在页面上准备一个div,用来装我们的面包屑导航,放在图表div的上方就行了:
<div className="breadcrumb" style={{ width: "100%", margin: "10px 0 0 30px" }}>
<span class='bread' val=''>全部 > </span>
</div>
二、图表的点击事件和面包屑导航的添加
再就是图表的点击事件,这是核心,为了更详细地解释,我把注释写在下方代码里:
// 点击表格柱状触发下钻
myChart.on('click', function (e) {
// 这里的name是我们的请求的条件
let name = e.name;
if (e.data.isLast === false) {
// 处理异步加载,防止用户多次点击
myChart.showLoading({
text: '正在加载数据',
color: '#fff',
textColor: '#fff',
maskColor: 'rgba(3, 27, 54, 0.7)',
zlevel: 999
});
// 组装好请求条件,下钻请求的参数一般就一个,比如时间等。也可以写多个参数,这里先说一个参数的处理,这是比较简单的
let param = {
infoDate: name
}
axios.get("写上你的url和参数一起给后台").then(res => {
// 下钻后,添加一个面包屑导航,记得设置一个自定义属性,来保存我们的请求条件,用于后面的导航跳转
$(".breadcrumb").append("<span class='bread' val='" + time + "'>" + e.name + " > </span>");
$(".bread").css({
color: "#fff",
cursor: "pointer"
});
// 每一个导航都要有点击事件,用于用户跳转不同的层级
$(".bread").each(function () {
$(this).unbind("click").click(function () {
// 每一次跳转,都记得清除面包屑导航右边的兄弟节点
$(this).nextAll().remove();
// 封装一个方法处理跳转后的数据展示,方法我在后面附上,这里that指向的是react,需要事先保存this指向
that.handleBread($(this).attr("val"));
})
});
// 拿到请求回来的数据后,就开始处理,我这里省略了部分非关键处理步骤,请根据自己图表来处理数据
let graphData = res.data.data;
option.series[0].data = graphData;
// 更新请求条件
that.setState({
infoDate: time
}, () => {
myChart.hideLoading(); // 记得关闭遮罩
myChart.setOption(option, true);
})
// 面包屑导航的鼠标移入移出事件
$(".bread").each(function () {
$(this).unbind("hover").hover(function () {
$(this).css({
color: "#1890ff",
cursor: "pointer"
})
}, function () {
$(this).css({
color: "#fff",
cursor: "default"
})
});
});
// 取消最后一个层级的面包屑导航的事件
// 由于面包屑导航本身还添加了事件,这一步可能不触发,所以每次图表初始化的时候再清除一下
$('.bread:last').off('mouseenter').unbind('mouseleave');
// 事件取消后发现样式还有问题,再进行一些微调
$(".bread:last").mouseenter(function () {
$(this).css({
color: "#fff",
cursor: "default"
})
})
}).catch((e) => { });
}
});
三、样式和事件的清除
这样一来,下钻的事件处理以及面包屑导航的添加就处理完了。代码的后面是一些导航样式的调整,比如鼠标移入高亮等,这类样式记得在图表初始化的时候清除一下。以及最重要的:清除点击事件,如下:
$(".bread").css({
color: "#fff",
cursor: "default"
})
$('.bread:last').off('mouseenter').unbind('mouseleave');
// 图表点击事件记得清除
myChart.off('click');
要是每次图表初始化不清除click点击事件,那么你会发现,每次事件都会多触发一次,面包屑导航越点越多。
四、面包屑导航点击事件的处理
最后一步就是面包屑导航的点击事件,每次点导航,我们还需要往回跳。
// 处理面包屑导航
handleBread(val) {
this.setState({
// 更新请求参数的变量
infoDate: val
}, () => {
/*
* 这个方法自己定义,作用就是请求后台数据然后再初始化图表
* 由于我们从自定义属性里面拿到了请求参数,每次只要重新请求后台就能拿到需要的数据
*/
this.requestData();
})
}
五、多参数处理的一点思路
其实理解上面几步的思路,功能就差不多能实现了。但是如果在项目中,后台的下钻参数不止一个(也就是让你传好几个)。好吧,啥需求都能遇上。这时候我们就要把参数都传过去,举例:
let param = {
mon: "", // 参数1:月份
type: "", // 参数2:类型
state: "", // 参数3:状态
}
下钻时拿到的值,必须给多个参数的其中一个,然而前端并不知道给哪个。所以我们一般需要后台给个标识(或者是根据后台数据来判断),用来判断赋予哪一个参数。只要把判断条件搞清楚了,多少个参数一样能传过去。
// flag类似于标识
if(flag === "mon"){
mon = data;
} else if (flag === "type"){
type= data;
} else {
state= data;
}
let param = {
mon: mon , // 参数1:月份
type: type, // 参数2:类型
state: state, // 参数3:状态
}
当然,这样一来,面包屑导航的span标签也不是只放val这一个自定义属性了,而是:
$(".breadcrumb").append("<span class='bread' mon='" + mon + "' type='" + type + "' state='" + state + "'>" + e.data.name + " > </span>");