JavaScript | 事件对象—滚动事件与加载事件

原文:JavaScript | 事件对象---滚动事件与加载事件

滚动事件与加载事件是前端中常见的事件类型,今天对这两个知识点进行下整理

滚动事件(scroll)

滚动事件顾名思义就是滚动页面或者说是某个元素滚动的时候就会触发的事件,可以使用以下几种方式触发滚动事件:

  • 鼠标滚轮滚动
  • 使用页面右侧的滚动条
  • 使用描点跳转
  • 调用JavaScript函数

如何添加滚动事件

  • DOM Level 2 中的写法(推荐使用):

    javascript 复制代码
    eventTarget.addEventListener('scroll', function(){
      console.log('触发了滚动事件');
    }); 
  • DHTML(DOM Level 0)的写法:

    javascript 复制代码
    EventTarget.onscroll = function () {
      console.log('触发了滚动事件');
    }

如何监听整个页面的滚动

如果想要监听整个网页的滚动,给window对象添加scroll事件即可

javascript 复制代码
window.addEventListener('scroll', function(){
  console.log('触发了滚动事件');
});

DHTML(DOM Level 0)的写法:

javascript 复制代码
window.onscroll = function () {
  console.log('触发了滚动事件');
}

事件节流

之前一篇博客有提到,如果在事件处理的回调函数调用了下面这些属性的话,就会引起回流与重绘(因为这些属性是实时读取的),而大量的回流与重绘就会造成浏览器的卡顿。

offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

所以可以使用节流的方式来缓解这个问题,先来了解下节流是什么:

节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率

实现方式:每次触发事件时,如果当前有等待执行的延时函数,则直接return终止此次事件的执行

代码:

JS:

javascript 复制代码
// 初始化 滚动标记 默认为false
let scrolling = false;

// 如果当前有滚动,则将滚动标记设置为true
window.addEventListener('scroll', function () {
  scrolling = true;
});

// 如果滚动事件触发,则每个300毫秒调用依次事件处理回调函数
setInterval(() => {
  console.log(scrolling);
  // 每次触发事件时,如果当前有等待执行的延时函数,则直接return
  if (!scrolling) {
    return;
  } else{
    // 立即设置为false
    scrolling = false
    // 处理逻辑
    window.scrollHandLer();
  }
}, 300);

function scrollHandLer() {
  // 滚动处理回调函数
  console.log('保护大籽然,不杀生');
}

加载事件(load)

加载事件,当外部资源(如图片、CSS、JavaScript文件等)加载完毕的时候触发的事件。

事件名:load

页面所有资源加载完毕后触发:

javascript 复制代码
window.addEventListener('load', function(){
  console.log('外部资源加载完毕');
});

DHTML(DOM Level 0)的写法:

javascript 复制代码
window.onload = function (){
  console.log('外部资源加载完毕');
}

使用场景:

在一些比较老的代码中会看到把script写在header中的写法,但是这样写会遇到一个问题

比如现在进入一个页面,会出现dom元素获取不到的问题,比如下面这种情况:

HTML:

html 复制代码
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    let div = document.querySelector('div');
    console.log(div); //null
  </script>
</head>
<body>
  <div></div>
</body>

控制台输出:null

所以就可以通过load事件来解决这个问题,代码如下

javascript 复制代码
window.addEventListener('load', function(){
  let div = document.querySelector('div');
  console.log(div);
});

控制台输出:<div></div>

当然,load事件不仅仅可以监听整个页面的资源加载,还可以针对某个资源绑定load事件

比如可以监听图片加载好之后给div元素放入文字

javascript 复制代码
let img = document.querySelector('img');
img.addEventListener('load', function () {
  let div = document.querySelector('div');
  div.innerHTML = 'test';
})

补充:DOMContentLoaded

当纯 HTML 被完全加载以及解析时,DOMContentLoaded事件会被触发,而不必等待样式表,图片或者子框架完成加载

------MDN-Document: DOMContentLoaded 事件

简单理解以下就是,页面的dom树加载完成后就会触发 ,也就是说这个事件的触发顺序实在load事件前面的。

事件名:DOMContentLoaded

监听页面的DOM加载完成------给document添加DOMContentLoaded事件即可

javascript 复制代码
document.addEventListener('DOMContentLoaded', (event) => {
  console.log('DOM fully loaded and parsed');
});

案例:

HTML:

html 复制代码
<div class="controls">
  <button id="reload" type="button">Reload</button>
</div>

<div class="event-log">
  <label>Event log:</label>
  <textarea readonly class="event-log-contents" rows="8" cols="30"></textarea>
</div>

JS:

javascript 复制代码
const log = document.querySelector('.event-log-contents');
const reload = document.querySelector('#reload');

reload.addEventListener('click', () => {
  log.textContent ='';
  window.setTimeout(() => {
      window.location.reload(true);
  }, 200);
});

window.addEventListener('load', (event) => {
    log.textContent = log.textContent + 'load\n';
});

document.addEventListener('readystatechange', (event) => {
    log.textContent = log.textContent + `readystate: ${document.readyState}\n`;
});

document.addEventListener('DOMContentLoaded', (event) => {
    log.textContent = log.textContent + `DOMContentLoaded\n`;
});

一些注意事项

  • DOMContentLoaded 事件在 html 文档加载完毕,并且 html 所引用的内联 js、以及外链 js 的同步代码都执行完毕后触发

  • 页面中引用的js 代码如果有异步加载的 js、css、图片,是会影响 load 事件触发的。

  • video、audio、flash 不会影响 load 事件触发。

参考文献

相关推荐
拆房老料6 小时前
ONLYOFFICE也能像Microsoft Word和WPS一样分别设置中西文字体
前端·html·word·开源软件·wps
Solis程序员6 小时前
Stripe 幂等表:把「不确定的重试」变成「查表返回」
前端·安全·bootstrap·php·agent
李纲明6 小时前
WordPress 站点变慢:按 TTFB → 缓存 → 查询 → 前端 分层排查(含配置注意)
前端·缓存·性能优化·wordpress·后端开发
程序人生8886 小时前
PDF 转 Word 版式错乱、表格丢失?DocConverter Web 格式互转引擎的保真实践
前端·人工智能·opencv·机器学习·pdf·word
粥里有勺糖7 小时前
安利一下最近用的桌面“Agent” | T3 Code
前端·github·ai编程
xy34537 小时前
Axure 9.0 动态面板基本操作
前端·ui·html·axure·原型·产品设计
不停喝水8 小时前
【前端转全栈java速通课】 项目实战④7-11节 操作数据库-登录-注册-修改密码-注销-mubatis-plus简化crud-
java·前端·数据库
一水鉴天8 小时前
统一对象拓扑(UOT)设计全链定稿:从三件事分离到三继承 之1 20261010(豆包“查看聊天内容”继续)
前端·css
杨杰3989 小时前
我给嵌入式设备写了个 6MB 的 JavaScript 运行时(xuan)
javascript
栖凤9 小时前
Java 的 try-catch 在 Agent 里失效了,我用了 5 个模式才兜住
java·前端·python