元素添加到页面时的事件
这是之前在这里讨论的: 如何使用Jquery将一个元素添加到页面时执行一个操作?
响应者build议每当div添加到页面时触发一个自定义事件。 不过,我正在编写Chrome扩展程序,无法访问页面源代码。 我在这里有什么select? 我想在理论上,我可以使用setTimeout
来持续search元素的存在,并添加我的动作,如果元素在那里。
由于DOM突变事件现在已被弃用 (请参见底部的注释)和最新的规范,你不能控制插入的元素,因为它们是由别人的代码添加的,唯一的select是不断地检查它们。
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 ); }
一旦调用这个函数,它将每xxx毫秒运行一次。 我select100次,这是每秒10次。 除非你需要实时的元素捕捉,否则应该就够了。
编辑
正如Ben Davis所说,DOM Level 4规范引入了Mutation观察者 (也在Mozilla文档上 ),它取代了被弃用的突变事件。
实际的答案是“使用突变观察者”(在这个问题中概述: 确定HTML元素是否已经dynamic添加到DOM ),但支持(特别是在IE)是有限的( http://caniuse.com/mutationobserver ) 。
所以实际的实际答案是“最终使用突变观察者……但是现在就和Jose Faeti的答案一起”:)
你可以使用jQuery的livequery
插件。 您可以提供一个select器expression式,例如:
$("input[type=button].removeItemButton").livequery(function () { $("#statusBar").text('You may now remove items.'); });
每次添加removeItemButton
类的button时,都会在状态栏中显示一条消息。
就效率而言,您可能想要避免这种情况,但无论如何,您都可以利用插件而不是创build自己的事件处理程序。
重新回答
上面的答案只是为了检测一个项目是否已经通过插件添加到了DOM中 。
然而,最有可能的是,一个jQuery.on()
方法更合适,例如:
$("#myParentContainer").on('click', '.removeItemButton', function(){ alert($(this).text() + ' has been removed'); }
例如,如果您的dynamic内容应该对点击做出响应,最好使用jQuery.on
将事件绑定到父容器。
您也可以利用CSS3animation事件,以便在将特定元素添加到DOM时得到通知: http : //www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/
ETA 24 Apr 17我想用一些async
/ await
魔法简化一下,因为它使得它更加简洁:
使用相同的promisified-observable:
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的东西,所以要认识到兼容性问题(例如,如果你的用户主要是阿米什语,luddite或者更糟的是IE8用户)
首先,我们将使用MutationObserver API构build观察者对象。 我们将这个对象包装在一个promise中,并resolve()
时,callback被激发(h / t davidwalshblog) 大卫沃尔什博客文章突变 :
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); }) }
然后,我们将创build一个generator function
。 如果你还没有使用过,那么你就错过了 – 但是一个简短的概要是:它像一个同步函数一样运行,当它find一个yield <Promise>
expression式时,它以非阻塞的方式等待要实现的承诺( 发电机做得比这更多,但这是我们在这里感兴趣的 )。
// 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") }
关于发电机的一个棘手的部分是他们不像一个正常的function“返回”。 所以,我们将使用一个辅助函数来像普通函数那样使用生成器。 (再次, 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突变整合到同步风格的控制stream程中。 怎么回事
有一个名为Arrive的有前途的JavaScript库,一旦浏览器支持变得平常,看起来像是一个很好的开始利用变异观察者的方法。
看看这个插件,做到了 – jquery.initialize
它的function非常像.eachfunction,不同之处在于它需要您select的select器,并在以后添加的新项目中匹配此select器并初始化它们
初始化看起来像这样
$(".some-element").initialize( function(){ $(this).css("color", "blue"); });
但是现在,如果新的元素匹配.some-element
select器将出现在页面上,它将立即初始化。
添加新项目的方式并不重要,你不需要关心任何callback等。
所以如果你想添加新的元素,如:
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
它会被立即初始化。
插件基于MutationObserver