【问题标题】:Recursive JQuery to format HTML node values in text递归 JQuery 以在文本中格式化 HTML 节点值
【发布时间】:2018-04-26 16:20:27
【问题描述】:

function insideNest(theindex, count) {
  count++;
  console.log("(\n)");
  if (theindex == null) {
    theindex = $(document);
  }
  $(theindex).children("#nest").each(function() {
    $(this).children("#value").each(function() {
      $(this).children("input").each(function() {
        for (i = 0; i < count; i++) {
          console.log("\t");
        }
        console.log($(this).val() + "\n");
      });
    });
    insideNest($(this));
  });
  console.log(")\n)");
}
$(document).ready(function() {
  insideNest($(this), -1);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="nest">
  <div id="value">
    <input type="text" id="hasvalue" value="level1" />
  </div>
  <div id="value">
    <input type="text" id="hasvalue" value="level1" />
  </div>
  <div id="value">
    <input type="text" id="hasvalue" value="level1" />
  </div>
  <div id="nest">
    <div id="value">
      <input type="text" id="hasvalue" value="level2" />
    </div>
    <div id="value">
      <input type="text" id="hasvalue" value="level2" />
    </div>
    <div id="nest">
      <div id="value">
        <input type="text" id="hasvalue" value="level3" />
      </div>
    </div>
    <div id="value">
      <input type="text" id="hasvalue" value="level2" />
    </div>
  </div>
  <div id="value">
    <input type="text" id="hasvalue" value="level1" />
  </div>
  <div id="value">
    <input type="text" id="hasvalue" value="level1" />
  </div>
</div>

我的输出:

(
)
)
)

预期输出:

level1
level1
level1
(
  level2
  level2
  (
    level3
  )
  level2
)
level1
level1

我想获取input 字段中的值,括号仅在嵌套#nest 时才开始。当javascript找到#nest时,我尝试调用相同的函数,并在找到#value时打印输出。我认为诀窍是只找到nest 的一级子级 小提琴:https://jsfiddle.net/2fq8u8wk/

【问题讨论】:

  • 您在文档中重复使用 ID,因此您的开端并不理想。我不知道 jQuery 是否只使用 .children() 强制执行一个结果。那些应该是一个类。

标签: javascript loops recursion


【解决方案1】:

我不知道您的错误的确切性质,因为我不想尝试分析 jQuery 的行为方式。

相反,重写会更容易。这是一个简单的递归函数,它使用本机 API 来执行您想要的操作。

function indent(n) { return "\t".repeat(n) }
function print(depth, s) { console.log(indent(depth) + s) }

function walk(root, depth) {
  print(depth, "(")
  
  for (const ch of root.children) {
    if (ch.matches(".value")) {
      print(depth + 1, ch.firstElementChild.value)

    } else if (ch.matches(".nest")) {
      walk(ch, depth + 1)
    }
  }
  print(depth, ")")
}

// Run after the DOM is loaded
document.addEventListener("DOMContentLoaded", function() {
  walk(document.body.querySelector(".nest"), 0)
})
<div class="nest">
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
  <div class="nest">
    <div class="value">
      <input type="text" class="hasvalue" value="level2" />
    </div>
    <div class="value">
      <input type="text" class="hasvalue" value="level2" />
    </div>
    <div class="nest">
      <div class="value">
        <input type="text" class="hasvalue" value="level3" />
      </div>
    </div>
    <div class="value">
      <input type="text" class="hasvalue" value="level2" />
    </div>
  </div>
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
</div>

我确实将您的 id 属性更改为 class,因为 ID 在文档中应该是唯一的。鉴于我上面的重写,我们可以摆脱 ID,但它仍然不是很好。

【讨论】:

  • 你能用jQuery来做这个吗?稍后添加到代码中的元素不会被脚本读取。
  • @code_together_today:jQuery 也是如此。如果您在 DOM 准备好之前运行它,那么这将是一个问题。我将添加代码以确保在加载 DOM 之前它不会运行。我不会用 jQuery 重写它,因为这是一个臃肿且不必要的依赖。
【解决方案2】:

基于 Crazy Train 的响应相似度,您可以创建访问函数。您可以控制每个节点在访问时、访问期间和访问后发生的情况。

const indent = (count, char) => (char || '\t').repeat(count);

function walkDom(node, preVisitFn, visitFn, postVisitFn, depth) {
  preVisitFn(node, depth);
  for (const child of node.children) {
    if (child.classList.contains('value')) {
      visitFn(child, depth + 1);
    } else if (child.classList.contains('nest')) {
      walkDom(child, preVisitFn, visitFn, postVisitFn, depth + 1)
    }
  }
  postVisitFn(node, depth);
}

walkDom(
  // The element we want to walk.
  document.body.querySelector('.nest'),

  // Before we visit children
  function(node, currentDepth) {
    console.log(indent(currentDepth) + '(')
  },

  // While we visit each child (depth +1)
  function(node, currentDepth) {
    console.log(indent(currentDepth) + node.firstElementChild.value)
  },

  // After all children have been visited
  function(node, currentDepth) {
    console.log(indent(currentDepth) + ')')
  },

  // Initial depth is zero.
  0
);
.nest { display: none; }

.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nest">
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
  <div class="nest">
    <div class="value">
      <input type="text" class="hasvalue" value="level2" />
    </div>
    <div class="value">
      <input type="text" class="hasvalue" value="level2" />
    </div>
    <div class="nest">
      <div class="value">
        <input type="text" class="hasvalue" value="level3" />
      </div>
    </div>
    <div class="value">
      <input type="text" class="hasvalue" value="level2" />
    </div>
  </div>
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
  <div class="value">
    <input type="text" class="hasvalue" value="level1" />
  </div>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-08-12
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多