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

forechartsAdd 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!

If you have any questions, thank you!