In the recent requirement, we need to draw tree diagram, and support to add/delete/convert child nodes. Performance issues are taken into consideration when operating. I have some feelings, and I just submitted today’s working code to record my thoughts.
The renderings to be achieved are as follows:
Draw a tree diagram
Since I have been using the Echarts library in my recent work, I naturally thought of the Tree implementation in Echarts. But PM prototype diagram of the connection line is a right Angle polyline, after investigation, Echarts4 are curves, the method found online said to modify the source code… So I looked at the configuration and learned that I could make a curve like the one above. In fact, I thought it was ok. Fortunately, PM also agreed. Properties: curveness
series: { data: currentData, lineStyle: { curveness: 1, }, ... defaultConfig, },Copy the code
The data structure is as follows, nested and nested and… :
{
"name": "Post"."type": 1,
"id": 1,
"children": [{"id": 2."prop": "yes"."name": "Branch 2"."type": 3."children": []}, {"id": 3."prop": "not"."name": "Text length >14"."type": 1,
"children": [{"id": 4."prop": "not"."name": "Virtual Node"."type": 2."children": [{"name": "Deletion rate >0.5"."type": 1,
"id": 5,
"children": []}]}, {"id": 8,
"prop": "yes"."name": "Branch 2"."type": 3."features": ""."children": []}]}Copy the code
Functions, as shown in the following right-click menu of these
forecharts
Add event binding
this.myChart.on('click', (param) => {
if(! param.seriesName)return;
const { data } = param;
});
this.myChart.on('contextmenu', (param) => {
if(! param.seriesName)return; console.log(param); / / return data below param. Event. The event. The preventDefault (); Const evt = param.event.event; Const {clientX, clientY} = evt; this.options = { x: clientX, y: clientY, }; this.menuVisible =true; this.currData = param.data; // Currently right-click target node});Copy the code
Performance issues
The returned node information is shown in the following figure. The node data we need is in the attribute data. Now the problem is that WE do not know where the node is in the total data.
The solution
In our data, each node has a unique identifier ID (not the database self-added ID, but the unique serial number of the front-end new node), and then the node ID +name is used as the key, and the node path path is used as the value.
For example, in the preceding JSON data, the node path whose ID is 4 is 0.children.1.children.0. Then, when processing the data, we can spell out the key according to the data we obtained, so as to extract the corresponding path, instead of going through the whole data every time we operate the node.
The following uses a node to be added as an example
const key = `${data.id}-${data.name}`;
const path = pathObj[key].split(', ');
letcurrList = {}; ForEach ((dot, index) => {if (index === 0) {
currList = this.nodes[dot];
return; } currList = currList[dot]; }); Freeze is used when storing nodes. Vue does not perform data hijacking to save performance. This.nodes.push ({id: ++ this.maxid, // this. MaxId, // the maximum id name in the existing data will be taken when initialized:'New node'.type: 4,
children: [],
}, {
id: ++this.maxId,
name: 'New node'.type: 3, children: [], }); // The path of the new child node should also be saved inhashThis.renderecharts (); / / updateCopy the code
In this way, we can get all the paths in one depth traversal. In the future, we only need to cycle the exact value of path each time, instead of doing depth or breadth traversal for the whole data multiple times.
conclusion
Although there are optimizations in the project for packaging and compilation using Webpack and so on, we should still consider performance issues when writing code. Small problems that may not be noticed can cause big problems in the end, over!