如何为一个div元素添加onload事件

311

如何向元素添加一个 onload 事件?

我能使用以下代码吗:

<div onload="oQuickReply.swap();" ></div>

为了这个做什么?


1
最好的 body 更好的 div - KingRider
2
div 元素不会“加载”。 - Armen Michaeli
1
现在有一个更相关的答案(https://stackoverflow.com/questions/58837574/is-there-an-equivalent-of-onload-or-a-hypothetical-onparse-for-standard-html),也许您可以修改接受答案? - mplungjan
27个回答

290
不行,你不能这样做。最简单的方法是在元素后直接调用函数。
例如:
...
<div id="somid">Some content</div>
<script type="text/javascript">
   oQuickReply.swap('somid');
</script>
...

或者 - 更好的方法是 - 就在</body>标签的前面:

...
<script type="text/javascript">
   oQuickReply.swap('somid');
</script>
</body>

...所以它不会阻止后续内容的加载。


4
根据用途的不同,将其放在</body>标签前面并不总是更好。例如,如果您希望仅在启用JavaScript时隐藏<div>,但又要避免"闪烁"效果。可见性时间取决于浏览器加载/解析所有内联/外部脚本所需的时间长短。 - mgutt
这是一种反模式吗?最好将所有js代码都放在自己的文件中吗?是否有一种方式可以在特定元素加载到文档中时选择性地运行js代码? - Ryan Walton
1
这不是反模式,但通常情况下您会等待DOM加载完成后再执行所有JS操作。 - DanMan
4
在这里为任何看到这篇答案的人提供一个链接 https://www.w3schools.com/tags/ev_onload.asp - 目前支持 onload 的所有HTML元素。 - Brandon Benefield
1
这个答案已经不再相关了。这里有一个新的答案 - mplungjan

104

使用onerror和没有src的IMG元素可以自动触发一些JavaScript。

<img src onerror='alert()'>

12
太棒了!还可以用来从Angular中触发TypeScript: img src (error)="function()" /> - Brian Richardson
1
这是一个非常棒的方法。请查看我对您的解决方案的扩展,链接在此处:https://dev59.com/wW855IYBdhLWcg3w-JQr#55106785 - Rounin
1
能用吗? - Pacerier
6
这是一个不太规范的解决方法... 但如果它能奏效的话... - Enrico
太好了!谢谢你! - voodoo98

89

onload 事件只能用于 document(body) 本身、框架、图像和脚本。换句话说,它只能附加到 body 和/或每个外部资源上。而 div 不是外部资源,它作为 body 的一部分加载,因此 onload 事件不适用于其上。


21
不仅可以在 body 元素上使用它,在图像和 iframe 等元素上也可以使用它,等等。http://www.w3schools.com/jsref/event_onload.asp - Joe
3
值得注意的是,内联脚本不是外部资源,因此没有 src HTML 属性的任何 <script> 都不能使用 onload(我曾尝试在内联脚本中使用这个建议,但发现它不起作用)。 - gog

50

页面加载事件只支持以下列出的少数标签。

<body>, <frame>, <iframe>, <img>, <input type="image">, <link>, <script>, <style>

这里是onload事件的参考资料。


20

试试这个!不要在div标记上触发两次!

您可以定义在div标记之前调用的函数。

$(function(){
    $('div[onload]').trigger('onload');
});

演示:jsfiddle


上面的jsfiddle没有jQuery加载器 - 也无法工作。 - Arif Burhan
@Arif Burhan,我不明白。我已经加载了JQuery(edge)。你能再检查一下吗?即使在移动设备上,我也可以看到“Hello World”。 - Kuofp
@Kuofp 那个小提琴实际上没有处理程序在它们的目标元素加载时被调用。它只是使用jQuery搜索具有属性(在您的情况下为onload)的元素,然后调用这些函数。即使将属性更改为其他内容(例如https://jsfiddle.net/mrszgbxh/),该脚本也可以正常工作。 - Trindaz
1
@Trindaz 没错!换句话说,这些脚本就像 onload 事件一样。感谢您留下评论! - Kuofp

10

我想补充一下,如果任何人想在 div 的加载事件上调用一个函数,而你不想使用 jQuery(因为像我这样的冲突),那么只需在所有 HTML 代码或任何其他代码(包括函数代码)编写完成后调用一个函数即可。

/* All Other Code*/
-----
------
/* ----At the end ---- */
<script type="text/javascript">
   function_name();
</script>

或者

/* All Other Code*/
-----
------
/* ----At the end ---- */
<script type="text/javascript">
 function my_func(){
   function definition;      

  }

 my_func();
</script>

你能用这种方式添加多个函数吗?即在HTML文档的末尾,就在</body>标签之前?如果可以,它们编写的顺序是否重要? - Neo
是的,您可以添加多个函数,顺序并不重要,这只是普通(原生)JavaScript。 - dev_khan

10

我需要在一段HTML(模板实例)插入后运行一些初始化代码,但是当然我没有访问操作模板和修改DOM的代码。同样的想法也适用于通过插入HTML元素(通常是<div>)部分修改DOM。

不久前,我使用一个几乎看不见的<img>元素的onload事件进行了一个hack,但是发现一个有范围的、空的style也可以做到:

<div .... >
<style scoped="scoped" onload="dosomethingto(this.parentElement);" >   </style>
.....
</div>

更新(2017年7月15日)- 在最新版本的IE中不支持<style> onload。Edge支持它,但是一些用户将其视为不同的浏览器并坚持使用IE。在所有浏览器中,<img>元素似乎更好地工作。

<div...>
<img onLoad="dosomthing(this.parentElement);" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" />
...
</div>

为了减少图片的视觉影响和资源使用,使用内联src来保持其小巧和透明。
关于使用

9
避免使用任何基于时间间隔的方法(因为它们不够高效和准确),而是使用 MutationObserver 监听动态加载的 div 的父级 div,以获得更好的效率。
更新:这是我写的一个方便的函数。像这样使用它:
onElementLoaded("div.some_class").then(()=>{}).catch(()=>{});

/**
 *
 * Wait for an HTML element to be loaded like `div`, `span`, `img`, etc.
 * ex: `onElementLoaded("div.some_class").then(()=>{}).catch(()=>{})`
 * @param {*} elementToObserve wait for this element to load
 * @param {*} parentStaticElement (optional) if parent element is not passed then `document` is used
 * @return {*} Promise - return promise when `elementToObserve` is loaded
 */
function onElementLoaded(elementToObserve, parentStaticElement) {
  const promise = new Promise((resolve, reject) => {
    try {
      if (document.querySelector(elementToObserve)) {
        console.log(`element already present: ${elementToObserve}`);
        resolve(true);
        return;
      }
      const parentElement = parentStaticElement
        ? document.querySelector(parentStaticElement)
        : document;

      const observer = new MutationObserver((mutationList, obsrvr) => {
        const divToCheck = document.querySelector(elementToObserve);

        if (divToCheck) {
          console.log(`element loaded: ${elementToObserve}`);
          obsrvr.disconnect(); // stop observing
          resolve(true);
        }
      });

      // start observing for dynamic div
      observer.observe(parentElement, {
        childList: true,
        subtree: true,
      });
    } catch (e) {
      console.log(e);
      reject(Error("some issue... promise rejected"));
    }
  });
  return promise;
}


实现细节:
HTML:
<div class="parent-static-div">
  <div class="dynamic-loaded-div">
    this div is loaded after DOM ready event
  </div>
</div>

JS:

var observer = new MutationObserver(function (mutationList, obsrvr) {
  var div_to_check = document.querySelector(".dynamic-loaded-div"); //get div by class
  // var div_to_check = document.getElementById('div-id'); //get div by id

  console.log("checking for div...");
  if (div_to_check) {
    console.log("div is loaded now"); // DO YOUR STUFF!
    obsrvr.disconnect(); // stop observing
    return;
  }
});

var parentElement = document.querySelector("parent-static-div"); // use parent div which is already present in DOM to maximise efficiency
// var parentElement = document // if not sure about parent div then just use whole 'document'

// start observing for dynamic div
observer.observe(parentElement, {
  // for properties details: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit
  childList: true,
  subtree: true,
});

@GorvGoyal 太棒了。 但我有一个场景:我们可能在 div 中有多个图像,它们的加载时间可能不同。 主要的事情是,当 div 内容完全加载时,我想调用一个函数。 与 window.onload 相同。 - Ankit Pandey
如果您有一个显示加载栏指示图像正在加载的div,那么您可以检查这个div。 - GorvGoyl
完美的GorvGoyl,观察得非常好!点赞 :) - user1781038

8
2019年11月,我正在寻求一种方法来创建一个(假设的)onparseEventListener,用于那些不使用onload<elements>
(假定的)onparse EventListener 必须能够监听元素解析的情况。

第三次尝试(和最终解决方案)

我对下面的第二次尝试非常满意,但我突然想到可以通过创建一个专门的事件使代码更短、更简单:
let parseEvent = new Event('parse');

这是目前最好的解决方案。

以下示例:

  1. 创建定制的parse Event
  2. 声明一个函数(可以在window.onload或任何时候运行),其中:
    • 查找文档中包含属性data-onparse的任何元素
    • parse EventListener附加到每个元素
    • 为每个元素分派parse Event以执行Callback

工作示例:

// Create (homemade) parse event
let parseEvent = new Event('parse');

// Create Initialising Function which can be run at any time
const initialiseParseableElements = () => {

  // Get all the elements which need to respond to an onparse event
  let elementsWithParseEventListener = document.querySelectorAll('[data-onparse]');
  
  // Attach Event Listeners and Dispatch Events
  elementsWithParseEventListener.forEach((elementWithParseEventListener) => {

    elementWithParseEventListener.addEventListener('parse', updateParseEventTarget, false);
    elementWithParseEventListener.dataset.onparsed = elementWithParseEventListener.dataset.onparse;
    elementWithParseEventListener.removeAttribute('data-onparse');
    elementWithParseEventListener.dispatchEvent(parseEvent);
  });
}

// Callback function for the Parse Event Listener
const updateParseEventTarget = (e) => {
  
  switch (e.target.dataset.onparsed) {

    case ('update-1') : e.target.textContent = 'My First Updated Heading'; break;
    case ('update-2') : e.target.textContent = 'My Second Updated Heading'; break;
    case ('update-3') : e.target.textContent = 'My Third Updated Heading'; break;
    case ('run-oQuickReply.swap()') : e.target.innerHTML = 'This <code>&lt;div&gt;</code> is now loaded and the function <code>oQuickReply.swap()</code> will run...'; break;
  }
}

// Run Initialising Function
initialiseParseableElements();

let dynamicHeading = document.createElement('h3');
dynamicHeading.textContent = 'Heading Text';
dynamicHeading.dataset.onparse = 'update-3';

setTimeout(() => {

  // Add new element to page after time delay
  document.body.appendChild(dynamicHeading);

  // Re-run Initialising Function
  initialiseParseableElements();

}, 3000);
div {
  width: 300px;
  height: 40px;
  padding: 12px;
  border: 1px solid rgb(191, 191, 191);
}

h3 {
position: absolute;
top: 0;
right: 0;
}
<h2 data-onparse="update-1">My Heading</h2>
<h2 data-onparse="update-2">My Heading</h2>
<div data-onparse="run-oQuickReply.swap()">
This div hasn't yet loaded and nothing will happen.
</div>


第二次尝试

下面的第一次尝试(基于@JohnWilliams的杰出的空白图片黑客)使用了硬编码的<img />并正常工作。

我认为完全可以删除硬编码的<img />,只有在检测到需要触发onparse事件的元素中存在类似以下属性时才动态插入它:

data-onparse="run-oQuickReply.swap()"

原来如此,这确实非常有效。
下面的示例:
1.查找文档中包含属性data-onparse的任何元素。 2.动态生成一个并将其附加到每个这些元素之后。 3.当呈现引擎解析每个时触发onerror EventListener。 4.执行回调并从文档中删除该动态生成的
工作示例:

// Get all the elements which need to respond to an onparse event
let elementsWithParseEventListener = document.querySelectorAll('[data-onparse]');

// Dynamically create and position an empty <img> after each of those elements 
elementsWithParseEventListener.forEach((elementWithParseEventListener) => {

  let emptyImage = document.createElement('img');
  emptyImage.src = '';
  elementWithParseEventListener.parentNode.insertBefore(emptyImage, elementWithParseEventListener.nextElementSibling);
});

// Get all the empty images
let parseEventTriggers = document.querySelectorAll('img[src=""]');

// Callback function for the EventListener below
const updateParseEventTarget = (e) => {

  let parseEventTarget = e.target.previousElementSibling;
  
  switch (parseEventTarget.dataset.onparse) {

    case ('update-1') : parseEventTarget.textContent = 'My First Updated Heading'; break;
    case ('update-2') : parseEventTarget.textContent = 'My Second Updated Heading'; break;
    case ('run-oQuickReply.swap()') : parseEventTarget.innerHTML = 'This <code>&lt;div&gt;</code> is now loaded and the function <code>oQuickReply.swap()</code> will run...'; break;
  }
  
  // Remove empty image
  e.target.remove();
}

// Add onerror EventListener to all the empty images
parseEventTriggers.forEach((parseEventTrigger) => {
  
  parseEventTrigger.addEventListener('error', updateParseEventTarget, false);
  
});
div {
  width: 300px;
  height: 40px;
  padding: 12px;
  border: 1px solid rgb(191, 191, 191);
}
<h2 data-onparse="update-1">My Heading</h2>
<h2 data-onparse="update-2">My Heading</h2>
<div data-onparse="run-oQuickReply.swap()">
This div hasn't yet loaded and nothing will happen.
</div>


首次尝试

我可以在JohnWilliams的《img src》黑客基础上继续构建(此页面来自2017年),这是迄今为止我遇到的最好方法。

下面是示例:

  1. 当渲染引擎解析时,触发onerror事件监听器。
  2. 执行回调并从文档中删除

工作示例:

let myHeadingLoadEventTrigger = document.getElementById('my-heading-load-event-trigger');

const updateHeading = (e) => {

  let myHeading = e.target.previousElementSibling;
  
  if (true) { // <= CONDITION HERE
    
    myHeading.textContent = 'My Updated Heading';
  }
  
  // Modern alternative to document.body.removeChild(e.target);
  e.target.remove();
}

myHeadingLoadEventTrigger.addEventListener('error', updateHeading, false);
<h2>My Heading</h2>
<img id="my-heading-load-event-trigger" src />


请参见:https://stackoverflow.com/questions/58837574/is-there-an-equivalent-of-onload-or-a-hypothetical-onparse-for-standard-html - Rounin
@DavidBradshaw - 你永远不会相信,但我认为我实际上已经解决了它。请看上面回答的第二次尝试 - Rounin
1
@DavidBradshaw - 刚才说的不算,我想出了第三种尝试。这是最终解决方案。 - Rounin
也许将答案削减到第三版。 - David Bradshaw
回顾这篇文章,15个月后我想知道你对这种方法的误解(我在15个月前没有意识到)可能源于你不熟悉“关注点分离”原则。 - Rounin
显示剩余10条评论

7
我们可以使用MutationObserver以高效的方式解决问题,下面附上一个示例代码。
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style>
        #second{
            position: absolute;
            width: 100px;
            height: 100px;
            background-color: #a1a1a1;
        }
    </style>
</head>
<body>
<div id="first"></div>
<script>
    var callthis = function(element){
           element.setAttribute("tabIndex",0);
        element.focus();
        element.onkeydown = handler;
        function handler(){
                alert("called")
        }
    }


    var observer = new WebKitMutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            for (var i = 0; i < mutation.addedNodes.length; i++)
            if(mutation.addedNodes[i].id === "second"){
                callthis(mutation.addedNodes[i]);
            }

        })
    });
    observer.observe(document.getElementById("first"), { childList: true });


    var ele = document.createElement('div');
    ele.id = "second"

    document.getElementById("first").appendChild(ele);

</script>

</body>
</html>

1
上次我检查时,突变事件表现得非常糟糕。 - DanMan

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