DOM 요소가 페이지에 추가 될 때 선택한 기능을 실행하고 싶습니다. 이것은 브라우저 확장과 관련이 있으므로 웹 페이지는 독립적으로 실행되며 소스를 수정할 수 없습니다. 내 옵션은 무엇입니까?
이론적 setInterval()
으로는 요소의 존재를 지속적으로 검색하고 요소가있는 경우 내 작업을 수행 하는 데 사용할 수 있지만 더 나은 접근 방식이 필요하다고 생각합니다.
DOM 요소가 페이지에 추가 될 때 선택한 기능을 실행하고 싶습니다. 이것은 브라우저 확장과 관련이 있으므로 웹 페이지는 독립적으로 실행되며 소스를 수정할 수 없습니다. 내 옵션은 무엇입니까?
이론적 setInterval()
으로는 요소의 존재를 지속적으로 검색하고 요소가있는 경우 내 작업을 수행 하는 데 사용할 수 있지만 더 나은 접근 방식이 필요하다고 생각합니다.
답변:
경고!
이 답변은 이제 구식입니다. DOM Level 4는 MutationObserver를 도입 하여 더 이상 사용되지 않는 돌연변이 이벤트를 효과적으로 대체합니다. 여기에 제시된 것보다 더 나은 해결책 은 이 답변 을 참조 하십시오. 진심으로. 100 밀리 초마다 DOM을 폴링하지 마십시오. CPU 전력을 낭비하고 사용자가 당신을 미워할 것입니다.
때문에 돌연변이 이벤트는 2012 년에 사용되지 않는, 당신은 그들이 다른 사람의 코드에 의해 추가되기 때문에 삽입 된 요소를 통제 할 수 없었다, 당신의 유일한 옵션은 지속적으로 그들에게 확인하는 것입니다.
function checkDOMChange()
{
// check for any new element being inserted here,
// or a particular node being modified
// call the function again after 100 milliseconds
setTimeout( checkDOMChange, 100 );
}
이 함수가 호출되면 100 밀리 초마다 1/10 (1/10) 초마다 실행됩니다. 실시간 요소 관찰이 필요하지 않으면 충분합니다.
MutationObserver()
: davidwalsh.name/mutationobserver-api
Event.ADDED_TO_STAGE
없습니까?
실제 대답은 "변이 관찰자 사용"(이 질문에 요약 된대로 : HTML 요소가 DOM에 동적으로 추가되었는지 확인 )이지만 지원 (특히 IE)은 제한되어 있습니다 ( http://caniuse.com/mutationobserver ). .
따라서 실제 실제 답변은 "돌연변이 관측기 사용 .... 결국입니다. 그러나 지금은 Jose Faeti의 답변과 함께 가십시오":)
변이 사건 의 폐기 와 출현의 출현 사이에 MutationObserver
, 특정 요소가 DOM에 추가 될 때 통지되는 효율적인 방법은 CSS3 애니메이션 사건 을 이용하는 것이었다 .
블로그 게시물을 인용하려면 :
DOM 노드 삽입 이벤트를 수신하려는 DOM 요소를 선택하여 (CSS 선택기 선택을 통해) CSS 키 프레임 시퀀스를 설정하십시오.
나는 비교적 친숙하고 거의 사용하지 않은 CSS 속성을 사용했습니다. 클립의도 된 페이지 스타일로 엉망을 피하기 위해 개요 색상을 사용했습니다. 코드는 한 번 클립 속성을 대상으로했지만 IE에서는 버전 11부터 더 이상 애니메이션 할 수 없습니다. 애니메이션을 적용 할 수있는 모든 속성이 작동하므로 원하는 것을 선택하십시오.다음으로 노드 삽입을 처리하기 위해 대리자로 사용하는 문서 전체의 animationstart 리스너를 추가했습니다. 애니메이션 이벤트에는 애니메이션을 시작한 키 프레임 시퀀스를 알려주는 animationName이라는 속성이 있습니다. animationName 속성이 노드 삽입을 위해 추가 한 키 프레임 시퀀스 이름과 동일해야합니다.
animationstart
, jsbin.com/netuquralu/1/edit 사용 사이에 30ms 이상의 차이가 있음을 보여줍니다 .
livequery
jQuery 용 플러그인을 사용할 수 있습니다 . 다음과 같은 선택기 표현식을 제공 할 수 있습니다.
$("input[type=button].removeItemButton").livequery(function () {
$("#statusBar").text('You may now remove items.');
});
removeItemButton
수업 버튼 이 추가 될 때마다 상태 표시 줄에 메시지가 나타납니다.
효율성 측면에서 이것을 피하고 싶을 수도 있지만, 어쨌든 자체 이벤트 핸들러를 작성하는 대신 플러그인을 활용할 수 있습니다.
재 방문 된 답변
위의 답변 은 플러그인을 통해 항목이 DOM 에 추가 되었음을 감지 하기 위한 것 입니다 .
그러나 다음과 같은 jQuery.on()
접근 방식이 더 적절할 것입니다.
$("#myParentContainer").on('click', '.removeItemButton', function(){
alert($(this).text() + ' has been removed');
});
예를 들어 클릭에 응답해야하는 동적 컨텐츠가있는 경우을 사용하여 이벤트를 상위 컨테이너에 바인딩하는 것이 가장 좋습니다 jQuery.on
.
ETA 24 4 월 17 일
나는 이것을 좀 더 간결하게 만들기 때문에 약간 async
/ await
마술로 이것을 단순화하고 싶었습니다 .
동일한 약속 된 관찰 가능 사용 :
const startObservable = (domNode) => {
var targetNode = domNode;
var observerConfig = {
attributes: true,
childList: true,
characterData: true
};
return new Promise((resolve) => {
var observer = new MutationObserver(function (mutations) {
// For the sake of...observation...let's output the mutation to console to see how this all works
mutations.forEach(function (mutation) {
console.log(mutation.type);
});
resolve(mutations)
});
observer.observe(targetNode, observerConfig);
})
}
호출 함수는 다음과 같이 간단 할 수 있습니다.
const waitForMutation = async () => {
const button = document.querySelector('.some-button')
if (button !== null) button.click()
try {
const results = await startObservable(someDomNode)
return results
} catch (err) {
console.error(err)
}
}
시간 초과를 추가하려면 다음과 같이 간단한 Promise.race
패턴 을 사용할 수 있습니다 .
const waitForMutation = async (timeout = 5000 /*in ms*/) => {
const button = document.querySelector('.some-button')
if (button !== null) button.click()
try {
const results = await Promise.race([
startObservable(someDomNode),
// this will throw after the timeout, skipping
// the return & going to the catch block
new Promise((resolve, reject) => setTimeout(
reject,
timeout,
new Error('timed out waiting for mutation')
)
])
return results
} catch (err) {
console.error(err)
}
}
실물
라이브러리없이이 작업을 수행 할 수 있지만 일부 ES6 항목을 사용해야하므로 호환성 문제를 인식해야합니다 (예 : 대상 사용자가 대부분 아미쉬, 황홀한 또는 IE8 사용자 인 경우)
먼저 MutationObserver API 를 사용하여 옵저버 객체를 생성합니다. 이 객체를 약속으로 마무리 resolve()
하고 콜백이 시작될 때 (h / t davidwalshblog) david walsh 블로그 기사 돌연변이에 대해 :
const startObservable = (domNode) => {
var targetNode = domNode;
var observerConfig = {
attributes: true,
childList: true,
characterData: true
};
return new Promise((resolve) => {
var observer = new MutationObserver(function (mutations) {
// For the sake of...observation...let's output the mutation to console to see how this all works
mutations.forEach(function (mutation) {
console.log(mutation.type);
});
resolve(mutations)
});
observer.observe(targetNode, observerConfig);
})
}
그런 다음을 만듭니다 generator function
. 아직 이것을 사용하지 않았다면 빠진 것이지만 간략한 개요는 다음과 같습니다. 동기 함수처럼 실행되고 yield <Promise>
표현식을 찾을 때 비 차단 방식으로 약속이 이루어질 때까지 기다립니다. 성취 됨 ( 제너레이터가이 이상을 수행하지만 이것이 우리가 관심을 갖는 부분입니다 ).
// we'll declare our DOM node here, too
let targ = document.querySelector('#domNodeToWatch')
function* getMutation() {
console.log("Starting")
var mutations = yield startObservable(targ)
console.log("done")
}
제너레이터에 대한 까다로운 부분은 정상적인 기능처럼 '돌아 오지'않는다는 것입니다. 따라서 도우미 함수를 사용하여 생성기를 일반 함수처럼 사용할 수 있습니다. (다시, h / t에서 dwb로 )
function runGenerator(g) {
var it = g(), ret;
// asynchronously iterate over generator
(function iterate(val){
ret = it.next( val );
if (!ret.done) {
// poor man's "is it a promise?" test
if ("then" in ret.value) {
// wait on the promise
ret.value.then( iterate );
}
// immediate value: just send right back in
else {
// avoid synchronous recursion
setTimeout( function(){
iterate( ret.value );
}, 0 );
}
}
})();
}
그런 다음 예상되는 DOM 돌연변이가 발생하기 전에 언제든지 실행하십시오 runGenerator(getMutation)
.
이제 DOM 변이를 동기식 제어 흐름에 통합 할 수 있습니다. 얼마나 시합?
브라우저 지원이 일반화되면 돌연변이 관찰자를 활용하는 좋은 방법처럼 보이는 유망한 자바 스크립트 라이브러리 인 Arrive가 있습니다.
정확하게이 플러그인을 확인하십시오- -jquery.initialize
각 기능과 같이 정확하게 작동합니다. 차이점은 입력 한 선택기가 필요하다는 것입니다.이 선택기와 일치하는 향후 추가 된 새 항목을보고 초기화합니다.
초기화는 다음과 같습니다
$(".some-element").initialize( function(){
$(this).css("color", "blue");
});
그러나 이제 새로운 요소 일치 .some-element
선택기가 페이지에 나타나면 즉시 초기화됩니다.
새 항목이 추가되는 방식은 중요하지 않으므로 콜백 등을 신경 쓸 필요가 없습니다.
따라서 다음과 같은 새 요소를 추가하려는 경우 :
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
즉시 초기화됩니다.
플러그인은 MutationObserver
순수한 자바 스크립트 솔루션 (없이 jQuery
) :
const SEARCH_DELAY = 100; // in ms
// it may run indefinitely. TODO: make it cancellable, using Promise's `reject`
function waitForElementToBeAdded(cssSelector) {
return new Promise((resolve) => {
const interval = setInterval(() => {
if (element = document.querySelector(cssSelector)) {
clearInterval(interval);
resolve(element);
}
}, SEARCH_DELAY);
});
}
console.log(await waitForElementToBeAdded('#main'));