代码之家  ›  专栏  ›  技术社区  ›  buggy1985

具有多个元素的jQuery UI Sortable抛出“TypeError:无法读取null的属性‘insertBefore’”

  •  3
  • buggy1985  · 技术社区  · 6 年前

    我正在尝试实现拖放(&A);使用以下示例中的多个元素拖放 this answer : http://jsfiddle.net/hQnWG/614/

    该示例在jQuery 1.9.1和jQuery UI 1.9.2(高达1.10.1)中运行良好,但一旦使用较新版本,如jQuery 1.11.3和jQuery UI 1.10.2或更新版本,我就会遇到以下问题。

    当选择多个元素并开始将最底部的选定元素缓慢拖动到顶部时,在它将捕捉到下一个位置之前,会抛出以下JS错误:

    Uncaught TypeError: Cannot read property 'insertBefore' of null
       at t.(/hQnWG/614/anonymous function).(anonymous function)._rearrange (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:7:15171)
       at t.(/hQnWG/614/anonymous function).(anonymous function)._rearrange (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:5:5028)
       at t.(/hQnWG/614/anonymous function).(anonymous function)._mouseDrag (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:7:6)
       at t.(/hQnWG/614/anonymous function).(anonymous function)._mouseDrag (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:5:5028)
       at t.(/hQnWG/614/anonymous function).(anonymous function)._mouseMove (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:5:12328)
       at t.(/hQnWG/614/anonymous function).(anonymous function)._mouseMove (https://code.jquery.com/ui/1.10.2/jquery-ui.min.js:5:5028)
       at HTMLDocument.o._mouseCapture._mouseDistanceMet._mouseDelayMet._mouseMoveDelegate (VM687 jquery-ui.min.js:5)
       at HTMLDocument.dispatch (VM251 jquery-1.11.3.min.js:4)
       at HTMLDocument.r.handle (VM251 jquery-1.11.3.min.js:4)
    

    下面是一个带有升级jQuery版本的JSFIDLE示例分支: http://jsfiddle.net/v3p6wsk2/6/

    我试图调试它,但找不到任何解释,说明拖动项的parentNode如何可以为null。 enter image description here

    我甚至找不到任何线索 jQuery UI 1.10.2. change log 关于什么改变了这可能会打破剧本。

    不幸的是,我无法更改我正在处理的项目中的版本。有没有可能在上述版本中实现这一点?

    2 回复  |  直到 6 年前
        1
  •  7
  •   KingWarin    6 年前

    据我所知,问题是 parentNode.insertBefore is called是被拖动的元素之一(已从原始表中删除),因此实际上不再有父元素。

    真正让我感到困惑的是,我认为问题不在 helper stop 函数,但介于两者之间,因为在 sort -事件。

    我不知道这个问题是从哪里来的,因为它在旧版本中运行,但通过试用&错误我可能已经找到了解决您问题的方法。

    您可以在将删除的元素插入列表后隐藏它们并删除隐藏的元素,而不是删除助手中的元素。

    看见 twistys fiddle I just updated

    这可能会解决您的问题,尽管这并不能解决(甚至无法找到)此问题的原因。

        2
  •  1
  •   Community Egal    4 年前

    因此,问题的根源在于:

    _rearrange: function(event, i, a, hardRefresh) {
      a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));
    
      //Various things done here to improve the performance:
      // 1. we create a setTimeout, that calls refreshPositions
      // 2. on the instance, we have a counter variable, that get's higher after every append
      // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
      // 4. this lets only the last addition to the timeout stack through
      this.counter = this.counter ? ++this.counter : 1;
      var counter = this.counter;
    
      this._delay(function() {
        if(counter === this.counter) {
          this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
        }
      });
    }
    

    当我使用未压缩版本生成错误时,我看到:

    Uncaught TypeError: Cannot read property 'insertBefore' of null
        at $.(anonymous function).(anonymous function)._rearrange (https://code.jquery.com/ui/1.10.3/jquery-ui.js:4628:68)
        at $.(anonymous function).(anonymous function)._rearrange (https://code.jquery.com/ui/1.10.3/jquery-ui.js:401:25)
        at $.(anonymous function).(anonymous function)._mouseDrag (https://code.jquery.com/ui/1.10.3/jquery-ui.js:3879:11)
        at $.(anonymous function).(anonymous function)._mouseDrag (https://code.jquery.com/ui/1.10.3/jquery-ui.js:401:25)
        at $.(anonymous function).(anonymous function)._mouseMove (https://code.jquery.com/ui/1.10.3/jquery-ui.js:933:9)
        at $.(anonymous function).(anonymous function)._mouseMove (https://code.jquery.com/ui/1.10.3/jquery-ui.js:401:25)
        at HTMLDocument._mouseMoveDelegate (https://code.jquery.com/ui/1.10.3/jquery-ui.js:911:16)
        at HTMLDocument.dispatch (https://code.jquery.com/jquery-1.11.3.min.js:4:8549)
        at HTMLDocument.r.handle (https://code.jquery.com/jquery-1.11.3.min.js:4:5252)
    Location: jquery-ui.js:4628
    

    这个 _rearrange 函数以条件操作开始。如果 a 存在,则 append 占位符Else insertBefore() 这个 parentNode 数组中特定元素的。

    那么,我猜是这样的 .insertBefore() 是DOM方法,而不是jQuery方法。根据结构, 返回节点 正在返回 null 要素

    HTML DOM parentNode属性

    返回值:节点对象,表示节点的父节点,或 无效的 如果节点没有父节点

    好的,我们确定了 i.item[0].parentNode 正在重新调整a 无效的 值并导致问题。

    我怀疑问题的关键是 helper 没有包装,因此每个项目位于 stop 没有 parent ;因此,没有 返回节点 。我认为解决方法是删除1个项,然后在其后附加其他元素,或者在另一个回调事件中附加这些元素。

    一旦我有更多的信息,我会更新这个。

    同样,这并不总是一个障碍,到目前为止,这只是基于Chrome的浏览器中的一个问题。

    更新1

    看起来像是从 停止 update 回调有帮助。两者的细微差别:

    停止(事件,ui)

    排序停止时触发此事件。

    VS公司

    更新(事件,ui)

    当用户停止排序且DOM位置已更改时,会触发此事件。

    我曾希望这就是诀窍。更新后我一开始没有得到它,后来我得到了它。必须继续工作。

    更新2

    这把小提琴在FF和Chromium中工作无误: https://jsfiddle.net/Twisty/wzuak8as/99/

    在创建 帮手 。我认为问题与这一行代码有关:

    return helper.append(elements);
    

    因此,这段代码表示我们正在返回一个jQuery对象, 帮手 ,这是 <li> 元素作为匿名函数的结果。同时,我们试图附加额外的jQuery对象, elements 进入 <li> 要素

    当我将代码调整为:

    helper.append(elements);
    return helper;
    

    错误不再出现。

    我回头查看了jQuery UI 1.9.2中的相同函数:

    _rearrange: function(event, i, a, hardRefresh) {
      a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
      //Various things done here to improve the performance:
      // 1. we create a setTimeout, that calls refreshPositions
      // 2. on the instance, we have a counter variable, that get's higher after every append
      // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
      // 4. this lets only the last addition to the timeout stack through
      this.counter = this.counter ? ++this.counter : 1;
      var counter = this.counter;
      this._delay(function() {
        if(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
      });
    }
    

    我找不到这两个图书馆的不同之处。我也无法找出为什么一个人操作时没有错误,而另一个人没有错误。它们应该是一样的。

    在我的测试中,我能够无误地运行代码。我希望这会有所帮助,你会把它作为答案。

    开发人员工具正在缓存控制台结果,我没有看到出现错误。我返回到您的原始代码,应用了更改,得到了相同的错误。