The applet realizes the multi selection function of TreeView tree

If you don't say much, let's start with the renderings:

The applet realizes the multi selection function of Treeview tree

Realization idea

Source data structure

First, our data structure is roughly:

[
  {
      "id": "0",
      "name": "classification of animals",
      "pid": "-1",
      "children": [
          {
              "id": "1",
              "name": "mammal",
              "pid": "0",
              "children": [
                  {
                      "id": "3",
                      "name": "dog",
                      "pid": "1",
                      "children": []
                  },
                  {
                      "id": "4",
                      "name": "cat",
                      "pid": "1",
                      "children": []
                  },
                  {
                      "id": "5",
                      "name": "elephant",
                      "pid": "1",
                      "children": []
                  }
              ]
          },
          {
              "id": "2",
              "name": "birds",
              "pid": "0",
              "children": [
                  {
                      "id": "6",
                      "name": "Magpie",
                      "pid": "2",
                      "children": []
                  },
                  {
                      "id": "7",
                      "name": "sparrow",
                      "pid": "2",
                      "children": []
                  },
                  {
                      "id": "8",
                      "name": "crow",
                      "pid": "2",
                      "children": []
                  }
              ]
          }
      ]
  }
]

id and pid are convenient to determine the relationship between parent and child nodes. These two items are essential regardless of the data structure provided by the server.
At the same time, because the data content of different developers will be different, we need to define a general Node object to change user data into a unified standard object for easy operation. As follows:

 /**
     * Create Node object
     */
    createNode(id, pid, lable) {
      let node = new Object();
      //Node id
      node.id = id;
      //Parent node id
      node.pid = pid;
      //written words
      node.lable = lable;
      //Upper level node (actually records the value of the index of the parent node)
      node.parentNode = null;
      //The data array of the next level child node (actually records the index value of the child node)
      node.childrenNode = [];
      //Expand
      node.isExpand = false;
      //Icon icon (+,)
      node.icon = -1;
      //Current level (level)
      node.level = 0
      //Check box
      node.checkbox = false;
      //Own index value
      node.index = -1;
      return node;
    },

Note: as for why the attribute values of parentNode and childrenNode are record indexes rather than objects, the reason is that the setData method of the applet needs to call json when sending js data to the wxml page Stringify() is converted to json string. If the value of parentNode or childrenNode is an object, there will be a reference to the object relationship, a circular reference error will be reported, and then the stack overflow exception will be called I don't think of a good solution for the moment. I can only save the country by curve. Find the specific Node object through index A small partner who knows a better solution can discuss it.

Convert the source data into a general array of nodes and sort to establish a parent-child relationship

Convert to a general Node array and sort

It is not difficult to convert it into a general Node Array and sort it. We put the data given to us by the server into the Node Array through recursive loop calls.
Some codes are as follows:

    getAllNodes(convertedNodesArray, array) {
      array.forEach(function (ele) {
        //Convert to node object
        let nodedata = _this.createNode(ele.id, ele.pid, ele.name);
        //Store in array
        convertedNodesArray.push(nodedata)
        //If there are child nodes, continue to call recursively
        if (ele.children.length > 0) {
          _this.getAllNodes(convertedNodesArray, ele.children);
        }
      })
    },

Through this recursive call, the data items in our collection should be [animal classification, mammals, dogs, cats, elephants, birds, sparrows, magpies, crows]; It's already in order

Establish parent-child relationship

It is easy to put the data into the node data and sort it, but how to establish the parent-child relationship (that is, assign values to the childNode and parenNode of the node)? The solution is to compare the current node and all subsequent nodes of the current node one by one:

  for (let i = 0; i < convertedNodes.length; i++) {
        //Current node
        let node = convertedNodes[i];
        node.index = i;
        for (let j = i + 1; j < convertedNodes.length; j++) {
          //Next node
          let nextNode = convertedNodes[j];
          if (nextNode.pid == node.id) {
            //Add the index of the child node to its childrenNode array
            node.childrenNode.push(j)
            //Adds the index of the parent node to the child node
            nextNode.parentNode = i;
          } else if (nextNode.id == node.pid) {
            nextNode.childrenNode.push(i);
            node.parentNode = j;
          }
        }
      }

Through the above operations, the data we have obtained are sorted and have a parent-child relationship (data horizontal display).
####Filter out the visible Node array
After sorting, not all our data will be displayed, so we need to filter out the visible Node array and really display the data to the page (the first level data is displayed by default). Remember that there is an isExpand attribute in our Node. This attribute value determines whether to display the current Node node. It is false by default, and only the isExpand status of the parent Node is true, Only isExpand of child Node is true Another attribute is parentNode, which is null by default. Only the parentNode of the root Node is null. We judge according to the values of these two attributes. The relevant codes are as follows:

        for (let i = 0; i < nodes.length; i++) {
        let node = nodes[i];
        //The child nodes (relative) expanded by the root node or parent node belong to the visible node
        if (_this.isRoot(node) || _this.isParentExpand(nodes, node)) {
          //Set the icon on the left to expandable
          _this.setParentNodeIcon(node)
          result.push(node);
        }
      }
   //Judge whether the parent node is expanded
    isParentExpand(nodes, node) {
      //If it is the root node
      if (node.parentNode == null) {
        return false;
      }
      //Get the index of the parent node and judge whether the parent node is open
      return nodes[node.parentNode].isExpand;
    },
    // Is it a root node
    isRoot(node) {
      //Determine whether it is a root node according to whether there is a parent node
      return node.parentNode == null
    },

About check boxes

The logic of the check box is: if the check box clicked by the user is the parent node, the corresponding child nodes should be selected. Similarly, if all child nodes are selected, the parent node should be selected automatically The implementation idea is: recursively call judgment, change the checkbox value of node, then filter out the visible node array, and then update the list with setdata

About expanding and closing lists

It is consistent with the implementation idea and logic of the check box

####Summary
I have used TreeView as a Component. After clicking OK, all data and status will be returned. Users only need to filter out the desired data display according to their own needs Please check the code for details.

TreeView checkbox

Keywords: Javascript html5 data structure Mini Program

Added by MartinGr on Fri, 24 Dec 2021 08:03:09 +0200