2015-01-07 4 views
2

Мне нужно предотвратить DOM-изменение с помощью mutationobserver.Может ли MutationObserver вносить изменения прямо перед мутацией?

Я был (в прошлом) следующий код, чтобы предотвратить определенные изменения:

document.bind("DOMSubtreeModified", function() { 
    document.find('.Xx.xJ:Contains("wham")').closest("[jsmodel='XNmfOc']").hide(); 
}); 

Из соображений производительности я не хотел, чтобы проверить полный текст документа на любой РОМ изменения, но только добавил содержание таким образом я изменил это (сейчас):

var observer = new MutationObserver(function (mutations) { 
     mutations.forEach(function (mutation) { 
      [].slice.call(mutation.addedNodes).forEach(function (addedNode) { 
       StartFilter(addedNode);      

      }); 
     }); 
    }); 

    observer.observe(document, { 
     childList: true, 
     subtree:true, 
     characterData:true, 
     attributes:true   
    }); 

function StartFilter(newNode) { 
    $(newNode).find('.Xx.xJ:Contains("wham")').closest("[jsmodel='XNmfOc']").hide(); 
} 

Но это на самом деле не работает. Я предполагаю, что «newNode» на самом деле не является ссылкой на DOM-Element. (Селектор действителен, "$(newNode).find('.Xx.xJ:Contains("wham")').closest("[jsmodel='XNmfOc']")" возвращает элемент).

Я не нашел никакого метода/свойства, чтобы отклонить dom-change в MutationObserver. Есть ли способ достичь того, чего я хочу БЕЗ проверки всего документа каждый раз?

ответ

1

Непонятно, является ли возвращаемый наблюдателем мутации NodeList «живым», в том смысле, что изменения в узлах в этом списке сразу отражаются на DOM. Но это не имеет значения, поскольку вы используете его только для создания набора jQuery. Основной код, который вы получили выше, работает по назначению (см. Упрощенный снимок ниже), что подразумевает, что есть что-то еще, препятствующее тому, чтобы ваш вызов hide() работал должным образом.

Мое лучшее понимание заключается в том, что вы не можете перехватывать и предотвращать изменения в DOM - MutationObserver запускается после того, как соответствующая мутация уже произошла. Это означает, что вы не прерываете или не перехватываете мутацию, а реагируете на нее. В вашем случае это может привести к неожиданному «мигающему» поведению, когда узлы будут добавлены, а затем удалены. Лучшим решением в этом случае было бы стирание вновь добавленных узлов, которые будут скрыты по умолчанию, а затем добавить класс/стиль, чтобы отображать их или удалять из DOM в фильтре-наблюдателе мутаций.

var container = document.querySelector('.container'); 
 
var addNodeButton = document.querySelector('#add'); 
 
var addNodeWithHideButton = document.querySelector('#addWithHide'); 
 

 
var makeAddNode = function(includeHide) { 
 
    return function() { 
 
    var p = document.createElement('p'); 
 
    var s = document.createElement('span'); 
 
    var msg = 'Appended at ' + new Date().getTime(); 
 
    if (includeHide) { 
 
     msg += ' (hide)'; 
 
    } 
 
    var t = document.createTextNode(msg); 
 
    s.appendChild(t); 
 
    p.appendChild(s); 
 
    container.appendChild(p); 
 
    console.log('appended::', p); 
 
    }; 
 
}; 
 

 
var makeNode = makeAddNode(false); 
 
var makeNodeWithHidden = makeAddNode(true); 
 

 
addNodeButton.addEventListener('click', makeNode); 
 
addNodeWithHideButton.addEventListener('click', makeNodeWithHidden); 
 

 
var toArray = function() { 
 
    return [].slice.call(arguments); 
 
}; 
 

 
var observer = new MutationObserver(function (mutations) { 
 
    mutations.forEach(function (mutation) { 
 
    toArray(mutation.addedNodes).forEach(function (addedNode) { 
 
     StartFilter(addedNode); 
 
    }); 
 
    }); 
 
}); 
 

 
observer.observe(document, { 
 
    childList: true, 
 
    subtree:true, 
 
    characterData:true, 
 
    attributes:true 
 
}); 
 

 
function StartFilter(newNode) { 
 
    var $n = $(newNode); 
 
    console.log('$n::', $n); 
 
    $n.find('span:contains(hide)').fadeOut(1500); 
 
    // $(newNode).find('.Xx.xJ:Contains("wham")').closest("[jsmodel='XNmfOc']").hide(); 
 
}
.container { 
 
    width: 80%; 
 
    border: 1px solid green; 
 
    padding: 1rem; 
 
    margin: 1rem auto; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<button id="add">Add node without "hide"</button> 
 
<button id="addWithHide">Add node with "hide"</button> 
 
<div class="container"></div>

+0

Спасибо за этого всеобъемлющего объяснения и примера. Особенно первый абзац помогает мне понять, что я, похоже, сталкивался с неправильным направлением. Вы должны заработать трофей для этого :) –

+0

Просто, если кому-то интересно: «Настоящая» проблема заключалась в том, что я поставил «наблюдатель var» внутри функции, которая была вызвана один раз вместо «корневой» области JS-файла –

+0

BTW: .hide() НЕ «мигает». DIV никогда не появляется (Chrome) :) –