" parentNode"的效率DOM API的属性?

时间:2017-05-15 17:06:05

标签: javascript dom browser

我即将编写一段代码,依赖import UIKit extension UIScrollView { func resizeScrollViewContentSize() { var contentRect = CGRect.zero for view in self.subviews { contentRect = contentRect.union(view.frame) } self.contentSize = contentRect.size } } 从当前节点所在的DOM树中查找属性。

例如:

scrollView.resizeScrollViewContentSize()

通过此标记,我希望能够单击parentNode并获取包含<div data-url="https://www.google.com"> <span> <a href='#' id='link'>Click me to get the url</a> </span> </div> 的最近祖先元素的<a>属性。

data-url

问题是我不确定这个data-url API的效率如何。它是否足够快我可以像对待常规javascript对象(使用API​​)一样对待它们?或者它实际上是否与回流相混淆或者与屏幕上的实际渲染元素有什么关系?

非常感谢任何见解!

[编辑]如果直接访问DOM树不是最好的选择,任何人都可以提出更好的选择吗?顺便说一句,我并不关心预处理东西所需的时间,所以如果解决方案涉及某些类型的预处理也很棒。

[EDIT2]更新为使用&#34; parentNode属性&#34;而不是&#34; parentNode函数&#34;

[EDIT3]我认为我给出这个具体的例子可能有点误导,因为它只是一个例子。底线是我已经有一个节点的引用(在这种情况下是var getEnclosingUrl = function(){ var link = document.getElementById('link'); var parent = link; while(parent = parent.parentNode){ if(parent.hasAttribute("data-url")){ return parent.getAttribute("data-url"); } } return "No url!"; } )并从那里开始,以获得包含该属性的最近祖先的特定属性。

基本上我正在寻找实现这一特定目标的最高效方法,并且不确定使用parentNode遍历DOM树是否足够好。

[编辑4]让我进一步澄清这一点。我希望能够在DOM树中获取任何元素,如下所示:

<a>

并访问其属性:

parentNode

并且以某种方式自动地它会找到具有该属性的最近的祖先(如果当前的那个没有),并返回该值,就像JS原型的工作方式一样。

2 个答案:

答案 0 :(得分:1)

首先,要了解有关使用DOM的一些事项。

  1. 它可能是最慢的API。
  2. 话虽如此,现代用户代理已经很好地优化了API,因此它不是以前的信天翁,并且对于大多数用例来说相当快,只要你不滥用它通过编写浪费的代码(见下文)。
  3. 无论使用哪种方法,搜索DOM都会产生开销,但单独搜索不会导致重新绘制或重排。

    访问属性值(甚至读取操作)也会增加额外的开销(因此请尽量减少循环中的DOM操作)。通常,最好将多个读操作分组为连续语句以优化操作。

    仅在修改元素的内容或样式时才会发生重绘和重排。在这些情况下,您可以采取一些步骤来最小化重新渲染,例如使用自己图层中的元素(最小化回流)并尽可能使用opacity

    根据您的情况,最好颠倒这种想法。不是在孩子处接收点击事件然后搜索父母,而是可以在父母处接收事件(通过冒泡),因为它是由孩子触发的。使用 event.currentTaget 在这里很有用,可以完全消除祖先的搜索循环:

    &#13;
    &#13;
    // Get a list of all the "parent" elements
    var dataURLs = document.querySelectorAll(".parent");
    
    // Assign event handlers to all the parent elements
    for(var i = 0; i < dataURLs.length; i++){
      dataURLs[i].addEventListener("click", function(e){
        // Get the value of the attribute ensuring to access
        // the object that the event was attached to, not the
        // object that initiated the event.
        console.log(e.currentTarget.dataset.url || "No data-url!");  
      });
    }
    &#13;
    <div data-url="https://www.google.com" class="parent">
      <span>
        <a href='#' id='link'>Click me to get the url</a>
      </span>
      <div>
        <!-- Even elements nested deeper within the parent will stil work -->
        <span>
          <a href='#' id='link'>Click me to get the url</a>
        </span>
      </div>
    </div>
    <div class="parent">
      <span>
        <a href='#' id='link'>Click me to get the url</a>
      </span>
    </div>
    <div data-url="https://www.microsoft.com" class="parent">
      <span>
        <a href='#' id='link'>Click me to get the url</a>
      </span>
    </div>
    <div data-url="https://www.apple.com" class="parent">
      <span>
        <a href='#' id='link'>Click me to get the url</a>
      </span>
    </div>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:1)

  

我正在寻找实现此特定目标的最高效方式,并且不确定使用parentNode来遍历DOM树是否足够

知道来自使用parentNode 不够好的测量结果之前,请勿尝试执行任何premature optimisation。使用parentNode属性是遍历DOM树的一种很好的方法,它的效率低下或其他东西并不为人所知。

如果确实存在问题,我会使用getEnclosingUrlWeakMap重写为递归方法并memoise