检测DOM元素的父级何时更改

时间:2014-09-18 15:35:28

标签: javascript html html5 dom

当元素parentElement发生变化时,是否会触发DOM事件?如果没有,有没有比超时轮询更好的方法?

我非常有兴趣了解parentElement何时从null更改为某个已定义的元素。也就是说,当某个DOM元素附加到文档树的某个地方时。

修改

鉴于评论中的问题,以下是一个示例,说明如何使用null parentElement创建元素:

var element = document.createElement('div');

console.assert(element.parentElement == null);

父级只有在添加到DOM后才会设置:

document.body.appendChild(element);

console.assert(element.parentElement != null);

另请注意,使用jQuery创建的元素在创建时也将具有null父级:

console.assert($('<div></div>').get(0).parentElement == null);

2 个答案:

答案 0 :(得分:3)

Afaik那里没有这样的&#34;父母听众&#34;。

然而,我发现了一个可能有用的黑客攻击。至少它值得一读,因为这个想法很聪明。

http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/

他在插入过程中使用CSS @keyframes并侦听生成的动画事件,告诉他该元素已被插入。

答案 1 :(得分:1)

1)这样的parentElementHasChanged event不存在。

2)解决方法 PISquared 指向可行,但对我来说看起来很奇怪。

3)在实践中,不需要这样的事件。如果一个元素在DOM中的位置发生变化,那么parentChange只会出现在元素中。为了实现这一点,你必须在执行此操作的元素上运行一些代码,并且所有代码都必须使用本机parent.removeChild(), 某处parent.appendChildparent.insertBefore()parent.replaceChild()。之后相同的代码可以运行回调,因此回调将是事件。

4)您正在构建库代码。该库可以为所有DOM插入/删除提供单个函数,它包含四个本机函数,并且&#34;触发事件&#34;。这是最后一次,也是我唯一想要避免频繁查找parentElement的内容。

5)如果需要包含原生Event API,您可以使用CustomEvent

创建 parentChanged 事件
element.addEventListener('parentChanged', handler); // only when  Event API needed

function manipulateElementsDOMPosition(element, target, childIndex, callback, detail) {
    if (!target.nodeType) {
        if (arguments.length > 4) return element;
        detail = callback; callback = childIndex; childIndex = target; target = null;
    }
    if (typeof childIndex === 'function') detail = callback, callback = childIndex;
    var oldParent = element.parentElement,
        newParent = target,
        sameParent = oldParent === newParent,
        children = newParent.children,
        cl = children.length,
        ix = sameParent && cl && [].indexOf.call(children, element),
        validPos = typeof childIndex === 'number' && cl <= childIndex;
    if (childIndex === 'replace') {
        (newParent = target.parentElement).replaceChild(element, target);
        if (sameParent) return element;
    } else {
        if (samePar) {
            if (!oldParent || ix == childIndex ||
                childIndex === 'first' && ix === 0 ||
                childIndex === 'last' && ix === (cl - 1)) return element;
            oldParent.removeChild(element);
        } else if (oldParent) oldParent.removeChild(element);
        if (!cl || childIndex === 'last') {
            newParent.appendChild(element);
        } else if (childIndex === 'first') {
            newParent.insertBefore(element, children[0])
        } else if (validPos) {
            newParent.insertBefore(element, children[childIndex]);
        } else return element;      
    }
    console.log(element, 'parentElement has changed from: ', oldParent, 'to: ', newParent);
    element.dispatchEvent(new CustomEvent('parentChanged', detail)); // only when Event API needed
    if (typeof callback === 'function') callback.call(element, oldParent, newParent, detail);
    return element;
}

一些示例用法(详细信息可能是您想要传递给事件/回调的任何内容)。函数总是返回元素。

// remove element
manipulateElementsDOMPosition(element /*optional:*/, callback, detail);
// prepend element in target
manipulateElementsDOMPosition(element, target, 'first' /*optional:*/, callback, detail);
// append element in target
manipulateElementsDOMPosition(element, target, 'last' /*optional:*/, callback, detail);
// add element as third child of target, do nothing when less than two children there
manipulateElementsDOMPosition(element, target, 3 /*optional:*/, callback, detail);
// replace a target-element with element
manipulateElementsDOMPosition(element, target, 'replace' /*optional:*/, callback, detail);