css Js无限循环问题中的树结构

jdzmm42g  于 2023-03-05  发布在  其他
关注(0)|答案(1)|浏览(92)

我有代码在Js中创建一个树结构,如果我使用add_child向elements数组中的一个项添加一个子项,它将添加到elements数组中所有项的子项,然后是子项,然后是子项,然后是子项,如此类推,它将创建一个无限循环
idk为什么它不工作

let divBase = {
  Name: "",
  Type: "div",
  children: [],
  open: false
};

let elements = [];

let elementCounter = 0;

function add_child(parentName, childName) {
  let parent = findItem(parentName)
  let child = removeItem(childName)

  console.log(parent)
  console.log(child)

  if (child != null) {
    parent.children.push(child)
    console.log(parent)
    console.log(child)
    return true
  }
  return false
}

function removeItem(itemName) {
  var returnitem = null;

  function findAndRemove(arr, itemName) {
    for (var i = 0; i < arr.length; i++) {
      var item = arr[i];
      if (item.Name === itemName) {
        returnitem = arr.splice(i, 1)[0];
        break;
      }
      if (item.children && item.children.length) {
        findAndRemove(item.children, itemName);
      }
    }
  }

  for (var i = 0; i < elements.length; i++) {
    var item = elements[i];
    if (item.Name === itemName) {
      returnitem = elements.splice(i, 1)[0];
      break;
    }
    if (item.children && item.children.length) {
      findAndRemove(item.children, itemName);
    }
  }

  return returnitem;
}

function findItem(item) {
  let result = null;

  function search(children) {
    for (let i = 0; i < children.length; i++) {
      const child = children[i];
      if (child.Name === item) {
        result = child;
        return;
      }
      if (child.children.length !== 0) {
        search(child.children);
      }
    }
  }

  search(elements);

  return result;
}

function selectItem(item) {
  let elements = document.getElementsByClassName("eitem");
  for (let i of elements) {
    i.style.backgroundColor = "rgb(24, 24, 24)";
  }
  document.getElementById(item).style.backgroundColor = "rgb(50, 50, 50)";
}

function getElementNum() {
  return elementCounter++;
}

function displayList(list, root, plase) {
  root.innerHTML = "";
  for (const item of list) {
    const itemEl = document.createElement("div");
    itemEl.className = "eitem";
    itemEl.id = item.Name;
    itemEl.draggable = true;
    itemEl.addEventListener("click", function() {
      selectItem(item.Name);
    });

    if (item.children.length != 0) {
      const button = document.createElement("button")
      const img = document.createElement("img")

      button.className = "eButton"
      img.className = "eImg"

      if (item.open == false) {
        img.src = "Icons/right.svg"
      } else {
        img.src = "Icons/down.svg"
      }

      button.appendChild(img)
      itemEl.appendChild(button)
    }

    const itemText = document.createTextNode(item.Name);
    const itemP = document.createElement("p");
    const itemb = document.createElement("b");

    itemP.className = "Etext";

    itemb.appendChild(itemText);
    itemP.appendChild(itemb);
    itemEl.appendChild(itemP);

    itemEl.addEventListener("dragstart", function(event) {
      event.dataTransfer.setData("text/plain", item.Name);
    });

    itemEl.addEventListener("dragover", function(event) {
      event.preventDefault();
    });

    itemEl.addEventListener("drop", function(event) {
      event.preventDefault();
      let target = event.dataTransfer.getData("text/plain")
      add_child(item.Name, target)
      displayList(elements, document.getElementById("Explorer_contaner"));
    });

    root.appendChild(itemEl);
  }
}

function add_element(element) {
  if (element === "div") {
    let newElement = Object.assign({}, divBase);
    newElement.Name = "Div " + getElementNum();
    elements.push(newElement);
    displayList(elements, document.getElementById("Explorer_contaner"));
    console.log(elements);
    return true;
  }
  return false;
}

如果我打印elements数组,它是这样的

(5) [{…}, {…}, {…}, {…}, {…}]

0 : {Name: 'Div 0', Type: 'div', children: Array(1), backgroundColor: '#2ecc71', width: 200, …}
1 : {Name: 'Div 1', Type: 'div', children: Array(1), backgroundColor: '#2ecc71', width: 200, …} 
2 : {Name: 'Div 2', Type: 'div', children:
> Array(1), backgroundColor: '#2ecc71', width: 200, …}
3 : {Name: 'Div 3', Type: 'div', children: Array(1), backgroundColor: '#2ecc71',
> width: 200, …}
4 : {Name: 'Div 5', Type: 'div', children: Array(1), backgroundColor: '#2ecc71', width: 200, …} length :  5

谢谢

q3qa4bjr

q3qa4bjr1#

使用递归函数时,需要确保它们终止,例如,在findItem()中,即使找到了节点,也要继续搜索。
请看更新后的版本,它在找到值后立即解析:

function findItem(item) {

  function search(children) {
    for (let i = 0; i < children.length; i++) {
      const child = children[i];
      if (child.Name === item) {
        return child; // <-------- we got it, terminate
      }
      if (child.children.length !== 0) {
        const inChild = search(child.children);
        if (inChild) return inChild // <-------- we got it further down, return that result
      }
    }
    return null // <------ nothing, keep going with outer function
  }

  return search(elements);
}

您的findAndRemove()也有同样的问题。
希望能有所帮助!

相关问题