非body元素的HTML:onload事件

6

我通常使用JQuery在许多元素上执行JavaScript转换的方法:

<div class="cow"></div>
<script> $(".cow").doStuff() </script>

然而,这种操作很脆弱:它假设页面只加载一次。一旦涉及到 Ajax 和部分重新加载,这种全局转换就会完全崩溃。如果服务器想基于某些服务器端数据对每个元素进行不同的转换,它也无法工作。
我知道非 body 元素的实际 onload 事件不起作用。一个解决方案是给所有元素提供 ID/Class 并立即使用 JQuery 引用它们。
<div id="cow"></div>
<script> $("#cow").doStuff() </script>

然而,这真的很混乱;我一点也不喜欢它,部分原因是每个我给一个ID的元素都会污染全局的I命名空间。目前,我正在为元素赋予一个有效的不可冲突的ID。

<div id="id877gN0icYtxi"></div>
<script> $("#id877gN0icYtxi").doStuff() </script>

基于随机的base64数字。然而,这一切似乎都像一个巨大的黑客行为:我可以简单地使用它们各自的属性给元素添加onclickonmousedown等,然后调用一个函数来转换给定的this

现在,我知道onload不起作用。然而,有没有办法模拟它的功能?具体地说,我想能够运行引用特定标记的javascript代码,使用this而不必为它们分配ID。

编辑:本质上,我想要类似于:

<input onclick="alert('moo')"/>

但对于oncreate而言,我的当前用例是填充一个inputtextarea文本框,我目前的做法是:

<input id="id877gN0icYtxi"/>
<script>$("#id877gN0icYtxi").val(...)</script>

每个输入框的...都不同,因此无法使用“全局”jquery转换轻松完成。另一方面,我不能在创建输入框时仅设置value或属性,因为它可能是textarea,我不知道。我想做这样的事情:

<input onload="$(this).val(...)"/>

这种方法不能正常工作,但我希望能够。再次提醒,...是由服务器设置的,并且对页面上每个input标签都不同。

编辑2:

我很清楚JQuery通常用于以相同方式对许多元素进行整个文档转换的情况。问题在于,在这种情况下,每个元素都以与该元素特定的方式进行转换,由服务器指定。具体用例是通过$().val()预填充每个字段的内容,自然每个字段将填充不同的内容。给每个元素一个唯一的 ID,并使用JQuery进行全局搜索来重新查找该元素似乎是一种非常迂回的方法,并且当您开始Ajax加载页面的某些部分时,它当然会出现问题。

编辑3:

简而言之,我想要能够编写以下内容:

<div onload="javascriptFunction(this)"/>

我希望当创建 <div> 时(无论是在初始页面上还是通过ajax插入),能够运行 javascriptFunction() 并将 <div> 作为参数传递。就像当单击 <div> 时,onclick 将以 <div> 作为参数运行 javascriptFunction() 一样,我希望在创建/插入 <div> 到DOM时发生相同的事情。
我愿意在<head>中接受任何数量的设置脚本,以实现此目的。出于上述原因,我不愿在<div>之后添加任何<script>标签,也不愿向<div>添加classid。在这些限制下,如何模拟非主体元素的onload属性是最好的呢?

2
你打算如何准确地识别你要处理的标签?有几种方法可以将你的标准转换为代码,但为了帮助你找出代码,我们需要先了解你的标准。 - dragon
这个东西http://docs.jquery.com/Plugins/livequery声称可以做到你想要的:“Live Query还具有在匹配新元素时触发函数(回调)以及在不再匹配元素时触发另一个函数(回调)的能力。”我自己没有测试过。 - Alfred Godoy
@dragon:onclick="alert(this)" 是一个在没有ID的情况下识别我正在处理的标签的示例。我想要类似的东西来引用元素在加载时,而不仅仅是在单击时。 - Li Haoyi
jQuery的“live”功能看起来很有趣;有没有人使用过它? - Li Haoyi
jquery.live()已被弃用,请尝试使用jquery.on()。在这种情况下,$('document').on('click', 'a', handler) - dragon
或者jquery.delegate()。它的作用和live一样,对吗?如果我错了,请纠正我。 - Parth Thakkar
4个回答

10

在DOM规范中并没有类似于onload事件,但是DOM Level 2规范提供了Mutation event types,以允许通知文档结构的任何更改,包括属性和文本修改,目前只有现代浏览器支持这些事件,在Internet Explorer 9中存在缺陷!

不过,您可以使用DOMNodeInserted事件来监视文档是否发生任何更改:

$(document).live("DOMNodeInserted", function(e){
  $(e.target).val(...);
});

使用Mutation事件时应该小心,至少要尽量更新!根据W3C:

Mutation事件类型尚未在用户代理之间完全和互操作地实现,正在开发新规范以解决Mutation事件解决的用例,但以更高效的方式。

我想如果您谷歌这个问题,您可能会找到一些跨浏览器/ jQuery插件,以防万一,这些链接可能有所帮助:

https://developer.mozilla.org/en/DOM/Mutation_events

http://help.dottoro.com/ljfvvdnm.php#additionalEvents

http://help.dottoro.com/ljmcxjla.php

http://help.dottoro.com/ljimhdto.php

http://www.bennadel.com/blog/1623-Ask-Ben-Detecting-When-DOM-Elements-Have-Been-Removed-With-jQuery.htm


1

所有这些都取决于您想要使用哪种标记。

需要知道的一件事是,jQuery允许您一次选择许多项目,因此当您执行像$('p')这样的操作时,该对象引用所有p节点。

执行像$('p').hide()这样的操作会隐藏所有p节点。

jQuery选择器(至少)与CSS选择器一样强大,因此您可以在单行中执行一些非常语义化的操作。

想象一下,如果您有一个回复框列表,用于评论部分或其他什么:

 -----------------------------------------
  Comment #1
   blah blah blah blah blah
    [ Text field  ] (Reply)
 -----------------------------------------
  Comment #2
   nyark nyark nyark nyark
    [ Text field  ] (Reply)
 -----------------------------------------
  Comment #3
   ubadabuba 
    [ Text field  ] (Reply)
 -----------------------------------------
  Comment #4
   eeeeeeeeeeeeeeeeeeeeeeeeee?
    [ Text field  ] (Reply)

因此,您的DOM布局可能看起来像这样

<div class="comment" >
    <h1> Comment #1 </h1>
   <p> blah blah blah blah blah </p>
    <input  /> <button >Reply </button>
</div>
<div class="comment" >
    <h1> Comment #2 </h1>
   <p> nyark nyark nyark nyark </p>
    <input  /> <button >Reply </button>
</div>

如果您想更新所有输入字段以放置默认文本,则只需查看字段的CSS选择器为.comment > input

之后JS会自动出现。

$(document).ready(function(){
    var inputs=$('.comment > input ');//references all the input fields defined by this selector
    inputs.attr('value','default text');//set the value of the text in the input
})​

这里展示的示例


0
将元素赋予 ID 并不会“污染全局命名空间”,它只是一种引用元素的机制。只需要为要按 ID 引用的元素赋予 ID。给其他元素赋予 ID 不会造成伤害,但也没有必要。
可以通过多种标准来引用元素,包括 class 和它们在 DOM 中的位置(CSS 选择器池中的任何方法以及 DOM 关系——父级、子级、兄弟等)。你选择的方法可能有优点和缺点,这取决于你如何使用它,没有绝对“好”或“最佳”的方法,只是有些方法比其他方法更适合某些情况。
如果你想在替换 DOM 中的元素后替换侦听器,则替换元素的循环需要考虑到这一点。事件委托是一种策略,还有其他方法。

是的,我知道这其中存在权衡;我已经非常彻底地考虑过了 =)。将所有的“给出元素ID,然后稍后执行$("#id").click(...)”的代码转换为简单地使用元素的onclick属性,在整个程序中节省了几十行代码,并且让正在进行的操作变得更加清晰明了。我希望对于所有在元素创建时需要运行的jquery转换都能做类似的事情。换句话说,如果不能自动完成,我不想让我的替换元素的代码替换掉所有的监听器,因为我将要替换大量的代码。 - Li Haoyi
如果您在标记中添加了侦听器,则克隆元素将保留侦听器。如果您动态添加侦听器,则除了在替换元素或使用未被替换的父级进行委派时再次添加它们之外,没有其他选项。 - RobG
这就是为什么我在问是否有任何方法可以在标记中添加onLoad监听器!或者使用一些一次性的JQuery技巧来实现相同的事情。再次添加它们的问题在于,我有很多东西被Ajax进来和出去,错误的可能性非常高。现在,它肯定会在短期内起作用,但从长远来看,它将增加代码库的混乱程度。 - Li Haoyi
如果您正在使用innerHTML插入HTML,则可以在插入的标记中包含侦听器。这比稍后动态添加它们要高效得多,并且还解决了其他问题。 - RobG

-1

关于 window.onload() 呢?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接