vue类似这样的拓扑图(我暂且叫它纵横拓扑图)使用什么前端插件工具构建?
可以使用D3.js
在vue类型的项目开发中,我们一般都是发起异步请求从服务器获取数据后,根据数组数据使用v-for来动态渲染数据列表。
但是,如果一个请求在pending中,再次发送一个请求,最后导致渲染的list,数据重复,或是错误的问题。
原因,就是多次请求了异步接口,一个接口没有返回,另外一个接口就发出去了。因为,ajax是一个异步操作。导致,在回调的时候,两次请求成功后的回调都会执行。就导致数据,错误了。
什么情况下发生这种现象呢? 譬如下拉滚动加载更多 或是 tab切换。
类似,这种,点击tab标签,根据list数据来渲染列表。
当快速切换tab标签时(可以把调试的网速降低,更容易看到这种情况),导致前一个标签的内容也会显示在第二个标签的内容里。
针对绘制类似于纵横线条的拓扑图的问题,推荐使用D3.js这个强大的前端数据可视化库来完成。D3.js包含大量的绘图模板和工具,可以帮助我们快速绘制各种图表,包括拓扑图。以下是一个简单的使用D3.js绘制拓扑图的代码示例:
// 定义画布大小
var width = 600,
height = 400;
// 创建SVG元素
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
// 定义节点数据
var nodes = [
{ id: 0, name: "Node 0" },
{ id: 1, name: "Node 1" },
{ id: 2, name: "Node 2" },
{ id: 3, name: "Node 3" },
{ id: 4, name: "Node 4" }
];
// 定义连线数据
var links = [
{ source: 0, target: 1 },
{ source: 1, target: 2 },
{ source: 2, target: 3 },
{ source: 3, target: 4 },
{ source: 4, target: 0 }
];
// 定义颜色比例尺
var color = d3.scaleOrdinal()
.domain(d3.range(nodes.length))
.range(d3.schemeCategory10);
// 创建力导向图模拟器
var simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-100))
.force("link", d3.forceLink(links))
.force("center", d3.forceCenter(width / 2, height / 2));
// 创建连线
var link = svg.selectAll(".link")
.data(links)
.enter()
.append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value); });
// 创建节点
var node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("circle")
.attr("class", "node")
.attr("r", 10)
.style("fill", function(d) { return color(d.id); })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
// 创建节点标签
var label = svg.selectAll(".label")
.data(nodes)
.enter()
.append("text")
.attr("class", "label")
.text(function(d) { return d.name; });
// 定义拖拽事件处理函数
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
// 定义帧渲染函数
function ticked() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
label.attr("x", function(d) { return d.x + 15; })
.attr("y", function(d) { return d.y + 5; });
}
// 注册帧渲染函数
simulation.on("tick", ticked);
代码中通过定义节点数据和连线数据来描述拓扑结构,然后通过D3.js创建力导向图模拟器,自动计算节点位置,并使用节点和连线数据渲染SVG元素。添加拖拽事件处理函数可以让用户交互性更加友好。这只是一个简单的示例,D3.js提供了丰富的API和组件可以让我们进一步优化图表效果。
注意,在使用D3.js等绘图工具时,需要仔细控制数据加载和重绘时机,避免数据出现重复或错误的情况,可以参考参考资料中“解决异步请求重复问题”的部分。