Home > Article > Backend Development > javascript - How to generate a three-level linkage menu tree based on the following array? (consider performance)
The first-level Id is a negative number, the parentId is empty, the second-level parentId is equal to the first-level id, and the third-level parentId is equal to the second-level id
[{"name": "Guangdong","Id": -1,"parentId": null} ,
{"name": "Hubei","Id": -2,"parentId": null},
{"name": "Guangzhou","Id": 44,"parentId": -1},
{"name": "Wuhan","Id": 58,"parentId": -2},
{"name": "Shenzhen","Id": 12,"parentId":-1 },
{" name": "白云","Id": 741,"parentId": 44}]
The first-level Id is a negative number, the parentId is empty, the second-level parentId is equal to the first-level id, and the third-level parentId is equal to the second-level id
[{"name": "Guangdong","Id": -1,"parentId": null} ,
{"name": "Hubei","Id": -2,"parentId": null},
{"name": "Guangzhou","Id": 44,"parentId": -1},
{"name": "Wuhan","Id": 58,"parentId": -2},
{"name": "Shenzhen","Id": 12,"parentId":-1 },
{" name": "白云","Id": 741,"parentId": 44}]
<code><div id="result"></div> <script> var result = document.getElementById('result') var arr = [ {"name": "广东","Id": -1,"parentId": null}, {"name": "湖北","Id": -2,"parentId": null}, {"name": "广州","Id": 44,"parentId": -1}, {"name": "武汉","Id": 58,"parentId": -2}, {"name": "深圳","Id": 12,"parentId":-1 }, {"name": "白云","Id": 741,"parentId": 44} ] var tree = {} var count = 0 array2Object(arr, tree, null) function array2Object (array, node, id) { var storage = [] var newArray = [] var newNode, newId for (var i = 0; i < array.length; i++) { if (array[i].parentId === id) { node[array[i].name] = {} storage.push(i) count++ } else { newArray.push(array[i]) } } if (count !== arr.length) { for (var i = 0; i < storage.length; i++) { array2Object(newArray, node[array[storage[i]].name], array[storage[i]].Id) } } else { object2Html(result, tree) } } function object2Html (node, obj) { var storage = [] var tpl = node.innerHTML + '<ul>' for (var key in obj) { tpl = tpl + '<li data-name="' + key + '">' + key + '</li>' if (!isEmptyObject(obj[key])) { storage.push({ name: key, obj: obj[key] }) } } tpl += '</ul>' node.innerHTML = tpl if (storage.length !== 0) { for (var i = 0; i < storage.length; i++) { object2Html(document.querySelector('li[data-name="' + storage[i].name + '"]'), storage[i].obj) } } } function isEmptyObject (obj) { for (var key in obj) { return false } return true } </script></code>
The effect is as shown in the picture
The writing is a bit ugly, but it is not limited to the sorting of the array (it does not have to be in descending order), nor is it limited to level 3.
In fact, this is a recursive relationship. Please post the code in my project:
<code> /** * 获取树的树形的下拉列表数组 * @param string $model 模型名称 * @param int $m 点位符数量 * @param string $pid 父级id * @param array field 字段名的数组 */ function dropdown_tree($model,$m=0,$pid=0,$field=array('id','sortname','parentid')) { $model=$model."_model"; $this->_CI->load->model($model); $class_arr=$this->_CI->$model->all(); $return_arr=array(); $this->dropdown_array($m,$pid,$class_arr,$return_arr,$field); return $return_arr; } /** * 遍历数组,修改其样式。 */ function dropdown_array($m,$pid,$class_arr,&$return_arr,$field){ $n = str_pad('',$m,'-',STR_PAD_RIGHT); $n = str_replace("-"," ",$n); foreach($class_arr as $item){ if($item["$field[2]"]==$pid){ $return_arr[$item["$field[0]"]]=$n."|--".$item["$field[1]"]; $this->dropdown_array($m+1,$item["$field[0]"],$class_arr,$return_arr,$field); } } }</code>
<code class="javascript"> var districts = [ {"name": "广东", "Id": 1, "parentId": 0}, {"name": "湖北", "Id": 2, "parentId": 0}, {"name": "广州", "Id": 3, "parentId": 1}, {"name": "武汉", "Id": 4, "parentId": 2}, {"name": "深圳", "Id": 5, "parentId": 0}, {"name": "白云", "Id": 6, "parentId": 3}, {"name": "江夏", "Id": 7, "parentId": 4}, {"name": "景云路", "Id": 8, "parentId": 6} ]; function arrayToTree(parentId) { var temp = []; for (var index in districts) { if (districts[index].parentId == parentId) { temp.push({ data: districts[index], children: arrayToTree(districts[index].Id) }); } } return temp; } function outputTree(items, depth) { var str = ''; for (var index in items) { /* repeat() 特性属于 ECMAScript 2015(ES6)规范 */ str += ' - - '.repeat(depth) + items[index].data.name + '<br/>'; if (items[index].children.length) { str += outputTree(items[index].children, depth + 1); } } return str; } var result = outputTree(arrayToTree(0), 0); document.write(result);</code>
<code class="javascript">广东 - - 广州 - - - - 白云 - - - - - - 景云路 湖北 - - 武汉 - - - - 江夏 深圳</code>
PS: The separator can be customized. Asking passing experts to help optimize: arrayToTree()
^_^
I have written it before, please click here directly, I am too lazy to copy it _^_.
If you are very concerned about performance, you can consider not using level 3 linkage because the order of magnitude is small, process it, and then enter the following Option.
Homepage
-Homepage
--Homepage
Homepage
Just find the classification based on the ID, and just use JQ to judge the record
Not invited to answer, (considering performance) I think it is most effective and direct to start at the source of the data, here is the database version.
Create table statement
<code>create table TP_CITY ( Id NUMBER , name VARCHAR2(255), parentId NUMBER ); insert into tp_city values(-1,'广东', null); insert into tp_city values(-2,'湖北', null); insert into tp_city values(44,'广州', -1); insert into tp_city values(58,'武汉', -2); insert into tp_city values(12,'深圳', -1); insert into tp_city values(741,'白云', 44); </code>
For example, use Oracle’s hierarchical query
<code>select lpad(' ', (level-1)*2, ' ')||name name from tp_city start with id<0 connect by parentId=prior Id;</code>
The returned results are as follows:
We can also write like this:
<code>select sys_connect_by_path(name, '-') path from tp_city start with id<0 connect by parentId=prior id; </code>
The return result is: