如何在 React / Backbone 环境中删除 JSPlumb-Element?

How to delete a JSPlumb-Element in a React / Backbone environment?

我有一个 backbonejs 模型集合,其中包含 JSPlumb 节点(ID、parentID)的模型。 DOM 表示由 React 处理(带有端点的 div)。如果我从集合中删除模型:

nodeCollection.remove(aNodeModel)

它连同所有包含的组件一起从 DOM 中删除 - 很好。

如果我现在添加一个新节点,则不会添加端点。我将此问题追溯到 JSPlumb 中的一些内部结构:如果我执行

jsPlumb.remove(aNodeModel.id)

端点问题消失了,但我得到了一个 React "Invariant Violation",因为 aNodeModel 没有从 nodeCollection 中删除。

如果我在从集合中删除模型之前手动删除 jsPlumb 端点:

jsPlumb.removeAllEndpoints(aNodeModel.id)

问题依旧。

这感觉有点像死锁...有什么建议吗?

开源 roxx。

我通过向 jsPlumb .remove() 方法添加一个参数来控制 jsPlumb 中元素的实际 DOM 删除来解决这个问题。如果我将其设置为 false jsPlumb 得到很好的清理,我可以让 React 删除实际的 DOM-element 之后:

jsPlumb.remove(sourceNodeID, false, [false]) 

这是我在 dom.jsPlumb-1.7.5.js 第 5176 和 5210 行中对 jsPlumb 源所做的更改。

var _doRemove = function(info, affectedElements, removeDOMElement) {
  _currentInstance.removeAllEndpoints(info.id, true, affectedElements);
  var _one = function(_info) {
    _currentInstance.getDragManager().elementRemoved(_info.id);
    _currentInstance.anchorManager.clearFor(_info.id);
    _currentInstance.anchorManager.removeFloatingConnection(_info.id);
    delete _currentInstance.floatingConnections[_info.id];
    delete managedElements[_info.id];
    delete offsets[_info.id];

    var actuallyRemoveDOMElement = true;            
    if (removeDOMElement.length > 0) {
      actuallyRemoveDOMElement = removeDOMElement[0];
    }

    if (_info.el) {
      if (actuallyRemoveDOMElement) {
        _currentInstance.removeElement(_info.el);
      }
      _info.el._jsPlumb = null;
    }
  };

  // remove all affected child elements
  for (var ae = 1; ae < affectedElements.length; ae++) {
    _one(affectedElements[ae]);
  }
  // and always remove the requested one from the dom.
  _one(info);
};


/**
 * Remove the given element, including cleaning up all endpoints registered for it.
 * This is exposed in the public API but also used internally by jsPlumb when removing the
 * element associated with a connection drag.
 */
this.remove = function (el, doNotRepaint, removeDOMElement) {
  var info = _info(el), affectedElements = [];
  if (info.text) {
    info.el.parentNode.removeChild(info.el);
  }
  else if (info.id) {
    _currentInstance.batch(function () {
      _doRemove(info, affectedElements, removeDOMElement);
    }, doNotRepaint === false);
  }
  return _currentInstance;
};