整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Out of的考点简明教程

一、out of的基本用法

Ⅰ.表示“在……外”之意:

1.The chemical plant is out of town.该化工厂在城外.

2.Our factory is 4 miles out of the city.我厂离城4英里.(指在城外,离城4英里.)

Ⅱ.表示“从……里”、“从……当中”之意:

1.We should remove the machine out of the room.我们应该把这台记起从室内搬出去.

2.Pump as much air as possible out of the container.尽可能地把容器内的空气都抽走.

3.You many choose one out of them.你可以从中选择一个.

4.This is only one instance out of many.这只不过是许多例子中的一例而已.

5. There was something coming to her and she was waiting for it, fearfully. What was it? She did not know, it was too subtle and elusive to name. But she felt it, creeping out of the sky, reaching toward her through the sounds,the scents,the color that filled the air.

有种东西正向她靠近,而她正恐惧地等待着。那是什么?她不知道。那东西太微妙太难以捉摸了,她说不清楚。但是她能感觉得到它,它正悄无声息地从天空中逸出,穿过弥漫于空气中的声音、气味和颜色慢慢地向她靠近。(it指的是freedom

Ⅲ.表示“接触”、“脱离”、“没有”、“缺乏”之意:

1.They have got out of many difficulties.他们已摆脱了许多困难.

2.The instrument went out of order.这个仪表发生故障.

3.That machine is out of repair.那台机器失修了(或损坏了).

4.Those devices are out of date.那些装置过时了.

5.They were often out of spare parts before liberation.解放前他们常缺少备件.

6.It is out of comparison.这是无可比拟的.

7.A new method was introduced are old one naturally.采用了新方法,旧方法自然就淘汰了.

8.Their workshop has run out of oxygen.他们的车间已用完氧气.

Ⅳ.表示来源、原因和动机之意:

1.He copied something new out of this book.他从这本书里摘抄了些新的内容.

2.They helped you out of pity.他们基于同情而帮助了你.

3.He went only out of curiosity.他仅仅是由于好奇心才去的.

4.He made this table out of an old box.他用一个旧木箱做成了这张桌子.

5.We did this out of necessary.我们出于需要做了这件事.

Ⅴ.表示“使……不……”和“使……取消……”之意:

1.We talked him out of his wrong plan.我们劝说他放弃他的错误计划.

2.They argued her out of violating the operating rules.他们说服她别违反操作规程.

二、带out of的一些常用词组举例(含义基本就是这个名词的相反的意思)

out of balance 不平衡,失去平衡

to go out of control(hand) 失去控制(无法收拾的)

out of doubt 无疑

out of focus 散聚

out of gear 混乱,发生故障

out of operation 不运转

out of fashion 过时,陈旧

out of joint 脱节

out of step 不同步,不一致

out of stock 脱销

out of touch 不接触

out of practice 荒疏

out of work 失业

The axle is out of true.轴的部位不正了

out of sight看不见

out of work失业

out of order发生故障

out of many difficulties摆脱了许多困难

out of repair失修(或损坏)

out of style过时,不时髦

out of business破产

out of date 过时

out of the ordinary 不寻常的

out of touch 失去联系

out of stock 脱销

out of patience 不耐烦

out of breath上气不接下气,喘不过气

out of the woods摆脱了前途不明,或危险的处境

Thank God he seems to be out of the woods now!他似乎渡过了危险期,真是谢天谢地。

out of the picture不再参与某项工程,或者退出某一行动

When I lived with my parents they had too many rules. These days I live by myself and can do as I please since they're now out of the picture. But I do miss them, so I visit them almost every weekend.

我以前和我父母一起住的时候,他们有好多规矩。现在我一个人住了,我愿意怎么做就怎么做,他们已经管不着了。但是,我很想他们,所以几乎每星期都回去看望他们。

out of this world令人激动,精彩极了,绝妙的,特别是在形容音乐、电影的时候可以用

Say, I see that Gone with the Wind is on TV tonight. I've seen it ten times already but I'll watch it again. I think it's out of this world--maybe the best movie ever made!

喂,今天晚上电视上要放《飘》这部电影。我已经看过十遍了,但是我今天还要再看一遍。我认为这个电影实在是太精彩了,可能是所有电影当中最好的一部。

Donna took me to lunch at a restaurant in a shady woods just outside of town. We sat outdoors and the food tasted great. The place is so pretty and relaxed that it's really out of this world!

唐纳带我到近郊一个隐蔽在树林里的饭馆去吃午饭。我们坐在户外。那里的饭菜色香味都好极了。那儿的环境非常漂亮和轻松。这实在是绝好的享受。

三、out of用法的注意点

Ⅰ.正确理解“from+out of+名词”的意义:

1.We should remove the device from out of the room at once.我们应该立即搬到室外的那个装置.

这里,介词短语“out of+名词”又作介词from的宾语.上句原意是:我们应该立即把这个装置从室外搬走.遇到这种“from+out of+名词”的词组,首先把“out of+名词”理解为“……外”,并作为一个整体概念来看待,然后早套上from(从)的意思即行.再如:

2.He is from out of town.他是城外人.

先把out of town理解为一个整体概念,即“城外”,然后套上from(从……)含义 ,故全句也可译为:他住在城外.

Ⅱ.根据有无其反义词in,into的搭配关系来选择和判断out of的含义.例如:

1.This plant is in town.这个工厂在城里.

That plant is out of town.那个工厂在城外.

2.They are in danger.他们处境危险.

He is out of danger.他已脱险.

3.This kind machine comes into fashion.这种机器正风行一时.

That kind of machine came out of fashion.那种记起不风行了(或“过时了”).

4.We talked him into making these experiments.我们劝说他做这些实验.

They talked him out of making these experiments.他们劝说他别做这些实验.

注:这种方法只能帮助我们选择out of 在句中的具体意义,而不能认为任何out of用法都有 in,into作其反义词.

Ⅲ.注意out of question和out of the question词义差别很大:

1.This is out of question an example of an important principle that applies to all machines.(作状语)这毫无疑问是适用于一切机械的一个重要原理的举例.

2.In the first instance,increasing the temperature is out of the question.(起形容词作用,作表语)在第一种情况下,提高温度是不可能的.

比较:

①Your success is out of question.(你一定成功。)

②Your success is out of the question.(你必定失败。)

内容是《Web前端开发之Javascript视频》的课件,请配合大师哥《Javascript》视频课程学习。

事件有很多类型,不同的事件类型具有不同的信息;

DOM2级事件规定了下列5种事件:

  • UIEvent(user Interface,用户界面)事件,在用户与页面上的元素交互时触发;
  • MouseEvent鼠标事件,当用户通过鼠标在页面上执行操作时触发;
  • KeyboardEvent键盘事件:通过键盘在页面上执行操作时触发;
  • HTML事件:当浏览器窗口发生变化或发生特定的客户端/服务器交互时触发;
  • MutationEvent变动事件:当底层DOM结构发生变化时触发;

DOM3级在DOM2的基础上重新定义了这些事件,并增加了一些事件:

  • FocusEvent焦点事件:当元素获得或失去焦点时触发;
  • WheelEvent滚轮事件:当使用鼠标滚轮(或类似设备)时触发;
  • 文本事件:当在文本中输入文本时触发;
  • 合成事件:当为IME(Input Method Editor,输入法编辑器)输入字符时触发;

HTML5规范也定义了大量的事件:历史管理、拖放、跨文本通信,以及多媒体等事件;

除了这些事件,有些浏览器会在DOM和BOM中也实现其他专有事件;

从另外一个角度来分,事件大致可以分成几大类:

依赖于设备的输入型事件:这些事件依赖于特定的输入设备,比如鼠标和键盘,也包括触摸事件;例如,mousedown、mousemove之类的,只能通过鼠标设备,而keydown或keypress只能通过键盘设备,touchmove或gesturechange也只能通过触摸设备实现;

独立于设备的输入型事件:不依赖于特定的输入设备,比如click事件,既可以通过鼠标单击实现,也可以通过键盘或触摸设备实现;再如textinput事件,即可以通过键盘按键实现,也可以在剪切和粘贴实现,甚至通过手写设备来实现;

用户界面事件:通常指的是一些注册在表单控件上的事件,例如文本框获取焦点的focus事件,控件改变值的change事件或提交表单的submit事件;

状态变化事件:表示某些生命周期或相关状态的变化的事件,比如,文档加载的load事件或DOMContentLoaded事件或文档状态readystatechange事件;再如HTML5的历史管理的popstate事件,online或offline事件;

特定API事件:HTML5及相关的规范中定义的事件,例如:拖放事件,多媒体的相关事件;

UIEvent事件:

UIEvent事件表示简单的用户界面事件,但包含一些不一定与用户操作有关的事件,主要与元素的焦点有关;

该事件类继承自Event类;由其也派生出其他子类,如MouseEvent、TouchEvent、FocusEvent、KeyboradEvent、WheelEvent、InputEvent和CompositionEvent;

其自身定义了一些属性,如:detail、layerX、layerY、pageX、pageY、sourceCapabilities、view和which;

UIEvent相关的事件:

  • DOMActive:表示元素已经被用户操作(通过鼠标或键盘)激活时发生;
  • load:当页面完全加载后在window上触发,当所有框架都加载完毕时在框架集上触发,当图像加载完毕时在<img>元素上触发,或者当嵌入的内容加载完成时在<object>元素上触发;
  • unload:当页面完全卸载后在window上触发,当所有框架都卸载后在框架集上触发,或者当嵌入的内容卸载完毕后在<object>元素上面触发;
  • abort:当用户停止下载过程时,如果嵌入的内容没有加载完,则在<object>元素上触发;
  • error:当发生Javascript错误时在window上触发,当无法加载图像时在<img>元素上面触发,当无法加载嵌入内容时在<object>元素上触发,或者当一或多个框架无法加载时在框架集上触发;
  • select:当用户选择文本框(<input>或<textarea>)中的一或多个字符时触发;
  • resize:当窗口或框架的大小变化时在window或框架上触发;
  • scroll:当用户滚动带滚动条的元素中的内容时,在该元素上触发;

以上这些事件,在DOM2级事件中,除了DOMActive之外,其他事件都属于HTML事件,所以,在确定浏览器是否支持DOM2级事件,最后检测一下,如:

var isSupported = document.implementation.hasFeature("HTMLEvents","2.0");

确定浏览器是否支持DOM3级事件,如:

var isSupported = document.implementation.hasFeature("UIEvent","3.0");

另外,这些事件,多数与window对象或表单控件相关,所以有些地方把这些事件也称为window事件,就是因为这些事件的发生多数与浏览器窗口有关;

load加载事件:当页面完全加载后(包括所有图像、Javascript文件和CSS文件等外部资源),就会触发window对象的load事件,这也是Javascript中最常使用的事件;

有两种定义onload事件处理程序的方式:

window.addEventListener("load", function(event){
    console.log("Loaded");
    console.log(event);  // Event
},false);
// 或在IE10以下
window.attachEvent("onload", function(event){
    console.log("Loaded");
    console.log(window.event);
});

为<body>元素添加onload特性;

<body onload="console.log(event);">

一般来说,在window上发生的任何事件都可以在<body>元素中通过相应的特性来指定,因为在HTML中无法访问window元素;

图像也可以触发load事件,无论是在DOM中的图像还是在HTML中的图像元素;

<img src="images/1.jpg" onload="alert('图片已加载')" />

或:

var img = document.querySelector("img");
img.addEventListener("load", function(event){
    console.log(event.target.src);
});
// 或
EventUtil.addHandler(img, "load", function(event){
    event = EventUtil.getEvent(event);
    console.log(EventUtil.getTarget(event).src);
});

在创建新的<img>元素时,可以为其指定一个事件处理程序,只需要指定src属性就可以下载,并不需要添加到DOM树中,如:

window.addEventListener("load", function(event){
    var img = document.createElement("img");
    img.addEventListener("load", function(e){
        console.log(e.target.src);
    });
    img.src = "images/1.jpg";
    document.body.appendChild(img);
});
// 或者
EventUtil.addHandler(window, "load", function(){
    var img = document.createElement("img");
    EventUtil.addHandler(img, "load", function(event){
        event = EventUtil.getEvent(event);
        console.log(EventUtil.getTarget(event).src);
    });
    img.src = "images/1.jpg";
    document.body.appendChild(img);
});

还可以使用DOM0级的Image对象实现,如:

    // 把
    var img = document.createElement("img");
    // 换成
    var img = new Image();

还有一些元素也以非标准的方式支持load事件;在标准浏览器中,<script>元素也会触发load事件,以确定动态加载的js文件是否加载完毕,在设置了<script>的scr属性并且添加到文档中,才会开始下载;

window.addEventListener("load", function(){
    var script = document.createElement("script");
    script.addEventListener("load", function(event){
        console.log(event.target.src);
    });
    script.src = "scripts/main.js";
    document.getElementsByTagName("head")[0].appendChild(script);
});
// 或
EventUtil.addHandler(window, "load", function(){
    var script = document.createElement("script");
    EventUtil.addHandler(script, "load", function(event){
        console.log(event);
        var target = EventUtil.getTarget(event);
        console.log(target.src);
    });
    script.src = "scripts/main.js";
    document.getElementsByTagName("head")[0].appendChild(script);
});

此时,event对象的target及currentTarget或srcElement引用都是<script>节点;

IE8及以下浏览器不支持<script>元素上的load事件,但以上代码不会抛出异常;

浏览器还支持<link>元素上的load事件,如:

window.addEventListener("load", function(){
    var link = document.createElement("link");
    link.rel = "stylesheet";
    link.addEventListener("load", function(event){
        console.log(event.target.href);
    });
    link.href = "styles/css.css";
    document.getElementsByTagName("head")[0].appendChild(link);
});

与<script>类似,指定其href属性并且添加到文档中才会下载;

unload事件:在页面被完全卸载后触发;或者从一个页面切换到另一个页面,或者刷新操作也会触发unload事件,如:

<body onunload="alert('unload');">

抛出异常:blocked alert during unload,也就是页面被阻塞了,而在unload事件处理中,是不允许阻塞的,诸如弹窗之类的,都会引起阻塞;正确的做法:

<body onunload="console.log('unload');">

或:

EventUtil.addHandler(window, "unload", function(event){
   console.log("unload");
});
  • unload事件特点:
  • unload事件的event对象只包含target(或srcElement)属性,且值为document;
  • unload事件发生时的状态应该是:
  • 所有资源仍存在 (图片, iframe 等.)
  • 对于终端用户所有资源均不可见;
  • 界面交互无效 (window.open, alert, confirm 等,会引起阻塞);
  • 错误不会停止卸载文档的过程;

unload事件执行时间很短,并且是在一切都被卸载之后才触发,所以不适合处理常规代码,一般是取消(或清除)该页面上的对象引用,以避免内存泄漏;

var obj = {name:"wangwei",age:18};
window.addEventListener("unload", function(event){
    var oDiv = document.getElementById("mydiv");
    console.log(oDiv);
    var img = document.getElementsByTagName("img")[0];
    console.log(img);
    console.log(obj);
    obj = null;
console.log(obj);
debugger;
});
var obj = {name:"wangwei",age:18};
window.addEventListener("unload", function(event){
    localStorage.setItem("unload","页面被unload了");
    localStorage.setItem("person", obj);
});

示例:统计一个页面停留的时长,如:

window.addEventListener("load", function(){
    var start = new Date();
    console.log(start);
    window.addEventListener("unload", function(){
        var end = new Date();
        var duration = (end.getTime() - start.getTime()) / 1000;
        var pageView = {
            pageStayTime: duration,
            pageUrl: location.href
        };
        console.log("保存到数据库中");
    });
});

另外,unload事件是不冒泡的,也是不可取消的;

同样,DOM2级事件规定应该在<body>元素而非window对象上触发unload事件,但所有浏览器都在window上实现了unload事件;

error事件:window.onerror属性看起来像事件处理程序,并且当Javascript出错时就会触发它,但是,它并不是真正的事件处理程序,因为它的参数不是event对象,而是5个参数,由这5个参数可以获取详细的错误信息;

  • message:错误信息,描述错误的一条消息;
  • URL:引发错误的Javascript所在的文档的URL;
  • line:文档中发生错误的行数;
  • column:发生错误的列数;
  • error:错误对象,这个error也称为全局错误对象;
window.onerror = function(sMessage, sUrl, sLine, sColumn, error){
console.log("Error:" + sMessage + " URL:" + sUrl + " Line:" + sLine + " Column:" + sColumn);
console.log(error);
    return true;
}

但如果使用DOM2级事件处理程序,其中的参数就是event对象;

window.onload = function(){
    num1 + num2;
}
window.addEventListener("error", function(event){
console.log(event);  // ErrorEvent
    return true;
});

ErrorEvent类继承自Event类,其定义了如下属性:

  • message:只读,返回包含了所发生错误的描述信息;
  • filename:只读,包含了发生错误的脚本文本的URL;
  • lineno:只读,错误发生的行号;
  • colon:只读,错误发生的列号;
  • error:只读,发生错误时所抛出的Error对象;

这5个属性也对应着window.onerror属性的5个参数;

如果是图片的onerror事件,就是一个真正的事件,其中只有一个参数,就是一个event对象;

var img = document.getElementsByTagName("img")[0];
img.onerror = function(event){
    console.log(event);  // Event type为error
}

abort事件:当一个资源的加载已中止时,将触发该事件;

var video = document.querySelector("video");
videoSrc = "https://www.zeronetwork.cn/video.webm";
video.addEventListener("abort", function(event){
    console.log(event);
    console.log("下载中止:" + videoSrc);
});
var source = document.createElement("source");
    source.setAttribute("src", videoSrc);
    source.setAttribute("type", "video/webm");
    video.appendChild(source);
source.addEventListener("error", function(event){
    console.log(event);
    return true;
});

resize事件:当浏览器窗口的大小被调整,就触发resize事件,该事件在window上触发;

EventUtil.addHandler(window, "resize", function(event){
    console.log(event);
});

在标准浏览器中,event对象有target属性,且值为window对象,但IE未提供任何属性;

浏览器的大小改变1像素就会触发resize事件,然后再随着变化不断重复触发;

最大化或最小化窗口时,也会触发resize事件;但是部分浏览器会在最大化或最小化时触发两次或以上的该事件,此时可以使用setTimeout()解决,也就是延迟执行某些代码,如:

function callBack(){
    console.log("callBack");
}
window.addEventListener("resize", function(event){
    var target = this;
    if(target.resizeFlag)
        clearTimeout(target.resizeFlag);
    target.resizeFlag = setTimeout(function(){
        callBack();
        console.log("resize");
        target.resizeFlag = null;
    },200);
});

示例:随窗口大小的变化而变化,如:

var mydiv = document.getElementById("mydiv");
var w = mydiv.clientWidth,
    h = mydiv.clientHeight,
    dx = w / h,
    dw = document.documentElement.clientWidth,
    scale = w / dw;
window.addEventListener("resize", function(event){
    var dw = document.documentElement.clientWidth;
    mydiv.style.width = dw * scale + "px";
    var w = mydiv.clientWidth;
    mydiv.style.height = w * dx * scale + "px";
    console.log(mydiv.style.width);
    console.log(mydiv.style.height);
});

示例:

<style>
*{margin:0;padding:0;}
.leftDiv,.rightDiv{
    width: 40%; overflow-y: scroll; float: left; margin-right: 10px; background-color: purple;
}
</style>
<div class="leftDiv">leftDiv ...</div>
<div class="rightDiv">rightDiv ...</div>
<script>
var leftDiv, rightDiv, dHeight;
window.addEventListener("load", function(){
    leftDiv = document.querySelector(".leftDiv");
    rightDiv = document.querySelector(".rightDiv");
    dHeight = document.documentElement.clientHeight;
    leftDiv.style.height = dHeight + "px";
    rightDiv.style.height = dHeight + "px";
});
window.addEventListener("resize", function(event){
    dHeight = document.documentElement.clientHeight;
    leftDiv.style.height = dHeight + "px";
    rightDiv.style.height = dHeight + "px";
});
</script>

resize事件目前只能注册在window对象上,它不支持注册在DOM元素上,如果要监听DOM元素的resize事件,最好的方案就是使用自定义事件;

scroll事件:虽然是在window对象上发生,但它实际表示的是页面中相应元素的变化;即可以在滚动窗口或其他元素时,跟踪变化来确保某些内容一直在屏幕上可见;

window.addEventListener("scroll", function(event){
    console.log(event);  // Event
});

该事件对象并没有提供滚动相关的信息,只是一个普通的Event的对象;

在混杂模式下,可以通过<body>元素的scrollLeft和scrollTop来监控到这一变化;在标准模式下,会通过<html>元素来反映这一变化;

window.onscroll = function(){
    console.log("x:" + document.documentElement.scrollLeft + ", y:" + document.documentElement.scrollTop);
}
// 或
window.addEventListener("scroll", function(event){
    if(document.compatMode == "CSS1Compat")
        console.log(document.documentElement.scrollTop);
    else
        console.log(document.body.scrollTop);
});

与resize事件类似,scroll事件会在文档被滚动活动期间会被重复触发,因此在scroll事件处理程序中尽量保持简单的代码;

scroll事件示例:

<div id="mydiv" style="width:200px;height:200px;background-color: purple; position: absolute;top:50px;right:50px;"></div>
<div style="height: 2000px; background-color:lightgreen;"></div>
<script>
window.onscroll = function(){
    var oDiv = document.getElementById("mydiv");
    oDiv.style.top = document.documentElement.scrollTop + "px";
}
</script>

scroll事件也可以注册到Element元素上;如:

var oDiv = document.getElementById("mydiv");
console.log(oDiv.scrollHeight);
oDiv.addEventListener("scroll", function(event){
    // console.log(event);  // Event
    console.log(event.target.scrollTop);
});

事件防抖(debounce)和节流(throttle):

防止事件被频繁触发;相关的事件有:mousemove、keydown、keypress、keyup、resize、scroll等;

防抖:触发高频事件后n秒内函数只执行一次,如果n秒内高频事件再次触发,则重新计算时间;如:

var timer = null;  // 创建一个标记用来存放定时器的返回值
window.addEventListener("resize", function(){
    if(timer){
        clearTimeout(timer);  // 每当resize时把之前的一个setTimeout清除
        timer = null;
    }
    if(!timer){
        timer = setTimeout(function(){ // 再创建一个新的定时器
            console.log("防抖");
        },500);
    }
});

在事件防抖中,清除定时器的时机很关键,必须在新定时器生成之前,如果在之后,会将所有定时器都清除,目标函数一次都不执行;或:

function debounce(callback, delay){
    var timeout = 0;
    return function(){
        var arg = arguments;
        // 一直触发,就一直清除
        clearTimeout(timeout);
        // 直到事件不再触发,最后一个定时器没有清除,delay后就会执行定时器,
        // 如此,就确保只执行一次
        timeout = setTimeout(function(){
            callback.apply(this, arg);
        }, delay);
    };
}
function fn(e){
    console.log("fn" + e);
}
window.addEventListener("resize", debounce(fn, 500));

示例:输入框验证

function checkEmail(callback,delay){
    var t = null;
    return function(){
        var arg = arguments;
        clearTimeout(t);
        t = setTimeout(function(){
            callback.apply(this, arg);
        }, delay);
    }
}
function emailHander(e){
    var reg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
    if(!reg.test(e.target.value)){
        e.target.style.backgroundColor = "red";
        setTimeout(function(){
            e.target.style.backgroundColor = "";
        },800);
        console.log("格式不正确");
    }else{
        e.target.style.backgroundColor = "green";
        console.log("正确");
    }
}
var email = document.getElementById("email");
email.addEventListener("keyup", checkEmail(emailHander,800), false);

节流:防抖是多次触发事件,目标函数只执行一次,不管触发这些事件用了多少时间;而节流是在一定时间内只会执行一次,稀释函数的执行频率,进而达到缓慢执行目标函数的目的;如:

使用setTimeout():

var timeoutId;
window.addEventListener("resize", function(event){
    if(!timeoutId){
        timeoutId = setTimeout(function(){
            console.log("延迟执行");  // 只执行一次
            clearTimeout(timeoutId); 
            // timeoutId = null;  // 换成这一句,500ms执行一次
        },500);
    }
});
// 或
function resizeHandler(event){
    // 先解除绑定
    window.removeEventListener("resize", resizeHandler);
    console.log(document.documentElement.clientWidth);
    // 重新绑定
    setTimeout(function(){
        window.addEventListener("resize", resizeHandler);
    },500);
}
window.addEventListener("resize", resizeHandler);

使用setInterval():

将事件处理程序放在setInterval()函数中,每隔一段时间,去监测一次是否发生了scroll事件,然后执行,而scroll事件只是改变scrolled的值,不会影响性能,如:

var scrolled = false;
window.addEventListener("scroll", function(){
    scrolled = true;
});
setInterval(function(){
    if(scrolled){
        // 代码处理
        console.log("scroll");
        scrolled = false;
    }
},500);

使用时间戳:

var startTime = new Date();
var flag = false;
var delay = 200;
window.addEventListener("resize", function(){
    startTime = new Date();
    if(flag === false){
        flag = true;
        setTimeout(resizeEnd, delay);
    }
});
function resizeEnd(){
    if(new Date() - startTime <= delay)
        setTimeout(resizeEnd, delay);
    else{
        flag = false;
        console.log(document.documentElement.clientWidth);
    }
}

或:

function thorttle(callback, delay){
    var timeout = 0;
    var now = new Date() - 0;
    return function(){
        var arg = arguments;
        var last = new Date() - 0;
        clearTimeout(timeout);
        if(last - now >= delay){
            now = last; // 将上次执行的时间赋值给now
        }else{
            // 目标函数在这里执行
            timeout = setTimeout(function(){
                callback.apply(this, arg);
            }, delay);
        }
    };
}
function fn(e){
    console.log("节流" + e);
}
window.addEventListener("resize", thorttle(fn, 500));

使用开关:

设置一个开关,一次只能有一个触发执行,并对执行设置计时一段时间再执行,执行完毕之后再解锁;如:滚动事件;

function loadMore(){
    var canRun = true;
    return function(){
        if(!canRun) return;
        canRun = false;
        setTimeout(function(){
            var docHeight = document.documentElement.offsetHeight; // 文档高度
            var winHeight = window.innerHeight;  // 窗口高度
            var scrollDistance = document.documentElement.scrollTop; // 滚动距离
            // 当滚动到底部时
            if(docHeight - (winHeight + scrollDistance) <= 100){
                console.log("Loading...");
            }
            canRun = true;
        },600);
    }
}
window.addEventListener("scroll", loadMore());

两者比较:

节流在某个时间段内,目标函数能执行一次,限制目标函数的执行频率,不管事件触发了多少次;

防抖是多次触发事件,目标函数只执行一次,不管触发了这些事件用了多少时间;

节流函数限制目标函数的执行频率,有连续变化的效果,适用于关注变化过程的操作,可以调整目标函数执行频率使得变化更加平滑,比如动画、改变窗口时执行某些操作等,常用事件resize、scroll、mouseWheel、touchmove、mouseover等;

防抖函数适用于更关注结果的操作,不太关注操作过程,常见的事件有 input、keyup等;

FocusEvent焦点事件:

焦点事件会在页面元素获得或失去焦点时触发,或某些对象调用了focus()和blur()方法也会触发该事件;利用这些事件并与document.hasFocus()方法及document.activeElement属性配合,可以知晓用户在页面上的行踪;

有以下6个焦点事件:

  • blur:在元素失去焦点时触发,该事件不会冒泡;
  • focus:在元素获得焦点时触发,该事件不会冒泡;
  • DOMFocusIn:在元素获得焦点时触发,该事件与HTML事件focus等价,但它冒泡;DOM3级事件废弃了它,应使用focusin;FF及低版本的IE不支持;
  • DOMFocusOut:在元素失去焦点时触发,该事件是HTML事件blur等价,但它冒泡;DOM3级事件废弃了它,应使用focusout;FF及低版本的IE不支持;
  • focusin:在元素获得焦点时触发,该事件与HTML事件focus等价,但它冒泡;
  • focusout:在元素失去焦点时触发,该事件是HTML事件blur等价,但它冒泡;

要确定浏览器是否支持这些事件,可以检测:

var isSupported = document.implementation.hasFeature("FocusEvent", "3.0");

可以获得焦点事件的元素一般指的是window或表单控件或是超链接或是可编辑元素,称为focusable元素;但在IE中普通元素也可以获得焦点;

window.onblur = function(){ document.title = "你离开了";};
window.onfocus = function(){ document.title = "你来了";};
var oDiv = document.getElementById("mydiv");
oDiv.contentEditable = true;
// oDiv.tabIndex = 1;  // 或者添加tabIndex属性也可以
oDiv.focus();
console.log(document.activeElement);
oDiv.addEventListener("focus", function(event){
    console.log(event.target.id);
});

这一类事件中最主要的两个是focus和blur,它们都是Javascript早期就得到所有浏览器都支持的事件,这两个事件的最大问题是它们不冒泡,因此,才出现了IE的focusin和focusout与Opera的DOMFocusIn和DOMFocusOut这两对事件,后来IE的方式被DOM3级事件纳为标准方式;

var btn = document.getElementById("btn");
btn.addEventListener("focus", function(event){
    console.log(event);  // FocusEvent
});

FocusEvent类:

表示和焦点相关的事件类,其继承自UIEvent类;

其自身只添加了一个属性relatedTarget,代表此次事件的相关目标,但在实用中,例如切换浏览器tab标签时,为了安全起见,所有浏览器都会返回null;

当焦点从页面中的一个元素移动到另一个元素,会依次触发下列事件:

blur在失去焦点的元素上触发、focusout在失去焦点的元素上触发、DOMFocusOut在失去焦点的元素上触发、focus在获得焦点的元素上触发、focusin在获得焦点的元素上触发、DOMFocusIn在获得焦点的元素上触发;但IE不遵循此顺序;

function handler(event){
    console.log(event.target.id + ":" + event.type);
}
var btn = document.getElementById("btn");
btn.addEventListener("DOMFocusIn", handler, false);
btn.addEventListener("DOMFocusOut", handler, false);
btn.addEventListener("focus", handler, false);
btn.addEventListener("blur", handler, false);
btn.addEventListener("focusin", handler, false);
btn.addEventListener("focusout", handler, false);
btn.focus();
var txt = document.getElementById("txt");
txt.addEventListener("focus", handler, false);
txt.addEventListener("blur", handler, false);
txt.addEventListener("DOMFocusIn", handler, false);
txt.addEventListener("DOMFocusOut", handler, false);
txt.addEventListener("focusin", handler, false);
txt.addEventListener("focusout", handler, false);

其中,blur、DOMFocusOut和focusout的事件目标是失去焦点的元素,而focus、DOMFocusIn和focusin的事件目标是获得焦点的元素;

另外,如果同时注册了focusin和DOMFocusIn或focusout和DOMFocusOut,在IE中只会触发focusin和focusout;

另外,除了focus和blur事件,其他事件只能通过DOM2级事件添加,如:

var btn = document.getElementById("btn");
btn.onfocusin = function(event){
    console.log(event);  // 不会触发
};
btn.onDOMFocusIn = function(event){
    console.log(event);  // 不会触发,IE会触发
};

onfocusin和onfocusout事件,在HTML事件处理中,除FF,其它都支持;DOMFocusIn和DOMFocusOut,在HTML事件处理中,都不支持;

小应用:改变文本框样式,如:

<style>
    .focusInput{border:1px solid purple;outline: none; background-color: rgba(0, 0, 0, .6);}
</style>
<script>
function focusInput(focusClass){
    var elements = document.getElementsByTagName("input");
    for(var i=0,len=elements.length; i<len; i++){
        var elt = elements[i];
        if(elt.type == "text"){
            elt.onfocus = function(){
                this.className = focusClass;
            };
            elt.onblur = function(){
                this.className = "";
            }
        }
    }
}
window.onload = function(){
    focusInput('focusInput');
}
</script>

focusin和focusout事件是冒泡的,因此可以使用事件代理,如:

<form id="myform" action="demo.jsp">
<input type="text" id="firstname" value="firstname" />    
<input type="text" id="lastname" value="lastname" />    
</form>
<script>
var myform = document.getElementById("myform");
myform.addEventListener("focusin", function(event){
    event.target.className = "focused";
});
myform.addEventListener("focusout", function(event){
    event.target.className = "";
});
</script>

示例:验证数据,如:

<style>
    .invalid{border-color:red;}
    #error{color:red}
</style>
<p>邮箱:<input type="email" id="email" /></p>
<div id="error"></div>
<script>
var email = document.getElementById("email");
var error = document.getElementById("error");
email.addEventListener("blur", function(event){
    if(!event.target.value.includes("@")){
        event.target.classList.add("invalid");
        error.innerHTML = "请输入正确的邮箱";
    }
});
email.addEventListener("focus", function(event){
    if(this.classList.contains("invalid")){
        this.classList.remove("invalid");
        error.innerHTML = "";
    }
});
</script>

或者使用focus()和blur()方法,如:

<style>
    .error{background-color: red !important;}
</style>
<p>邮箱:<input type="email" id="email" /></p>
<script>
var email = document.getElementById("email");
email.addEventListener("blur", function(event){
    if(!event.target.value.includes("@")){
        event.target.classList.add("error");
        event.target.focus();
    }else
        event.target.classList.remove("error");
});
</script>

示例:一个HTML编辑器;

<style>
.container,.editor{width:400px; height: 150px; display: block;}
.container{padding: 2px; border:1px solid;}
.editor{padding: 0; border:2px solid blue;}
.editor:focus{outline: none;}
</style>
<div id="container" class="container">
    <h1>Web前端开发</h1>
</div>
<script>
var area = null;
var container = document.getElementById("container");
container.addEventListener("click", function(event){
    editStart();
},false);
function editStart(){
    area = document.createElement("textarea");
    area.className = "editor";
    area.value = container.innerHTML;
    area.addEventListener("keydown", function(event){
        if(event.keyCode == 13)
            this.blur();
    },false);
    area.addEventListener("blur", function(event){
        editEnd();
    });
    container.replaceWith(area);
    area.focus();
}
function editEnd(){
    container.innerHTML = area.value;
    area.replaceWith(container);
}
</script>

当用户按下Enter键或失去焦点时,<textarea>变回<div>,其内容在<div>中变为HTML;

DOM3级事件规定了以下几类事件:

  • UI事件(UIEvents),当用户与页面上的元素交互时触发
  • 焦点事件,当元素获得或失去焦点时触发
  • 鼠标事件(MouseEvents),当用户通过鼠标在页面上执行操作时触发
  • 滚轮事件(),当使用鼠标滚轮时触发
  • 文本事件,当在文档中输入文本时触发
  • 键盘事件(KeyboardEvent),当用户通过键盘在页面上执行操作时触发
  • 合成事件,当为IME输入字符时触发
  • 变动事件(MutationEvents),当底层DOM结构发生变化时触发

不同的事件类型具有不同的信息。此外,有些浏览器还会在DOM和BOM中实现其专有事件,HTML5还定义了一组事件。

我们可以通过document.createEvent(type)来创建一个事件(已有的事件或者自定义事件都可以)

// 创建一个事件
var event = document.createEvent("Event");
// 初始化事件的相关信息
event.initEvent("build", true, true);
// 元素可以监听这个事件
el.addEventListener("build", function(e){
 // 做处理
}, false);
// 需要在脚本中触发事件,就会执行相对应的回调
el.dispatchEvent(event);

1. UI事件

常见的UI事件有

  • load/unload
  • abort
  • error
  • select
  • resize
  • scroll

1.1 load/unload 事件

会触发load事件的情况:

  • 页面完全加载后(包括所有外部资源),会触发window上面的load事件
  • 图像的加载也会触发load事件,无论是<img>标签还是Image对象,但要注意的是在IE8及之前版本不会生成event对象。
  • 在IE9+、firefox、opera、chrome、safari3+等浏览器中,<script>也会触发load事件,以便开发人员确定动态加载的js文件是否加载完毕。
  • IE和Opera还支持<link>元素上的load事件

与load事件对应就是unload事件,这个事件在文档被完全卸载后触发,其实用户从一个页面切换到另一个页面就会发生unload事件,而利用这个事件最多的情况是清除引用,以避免内存泄漏。

另外说明一点,通常我们会在页面中看到:

<!DOCTYPE html>
<html>
 <head>
 <title>example</title>
 </head>
 <body onload="" onunload="">
 
 </body>
</html>

一般来说,在window上面发生的任何事件都可以在body元素中通过相应的属性来指定,因为在HTML中无法访问window对象,实际上,这只是为了保证向后兼容的一种权宜之计,但所有浏览器都能很好地支持这种方式。

1.2 resize事件

当浏览器窗口被调整到一个新的高度或宽度时,就会触发resize事件,这个事件在window上面触发。

浏览器窗口最小化或最大化时也会触发resize事件。

resize事件可能会被频繁触发,浏览器会有一些机制来保证两个resize事件触发有一定的间歇(例如20ms),我们自己在处理的时候也要特别注意,详情见函数节流。

1.3 scroll事件

  • scroll事件是在window对象上发生的,但它实际表示的则是页面中相应元素的变化。
  • 在混杂模式下,可以通过body元素的scrollLeft和scrollTop来监控这一变化。
  • 在标准模式下,除了safari(仍然是通过body),所有浏览器都会通过html元素来反应这一变化。
window.addEventListener("scroll", function(e){
 if(document.compatMode == "CSS1Compat"){
 alert(document.documentElement.scrollTop);
 } else {
 alert(document.body.scrollTop);
 }
}, false);

需要注意的是,scroll事件在文档被滚动期间会被重复地触发,跟resize的处理类似。

2. 焦点事件

焦点事件会在页面元素获得或失去焦点时触发,利用这些事件并与

  • document.hasFocus()
  • document.activeElement

就可以知晓用户在页面上的行踪。

常见焦点事件共有:

  • blur:在元素失去焦点时触发,这个事件不会冒泡,所有浏览器都支持
  • focus:在元素获得焦点时触发,这个事件不会冒泡,所有浏览器都支持
  • focusin:在元素获得焦点时触发,这个事件与HTML事件focus等价,但是会冒泡。支持的浏览器有IE5.5+、opera 11.5+、chrome、safari 5.1+
  • focusout:在元素失去焦点时触发,这个事件与HTML事件blur等价,支持的浏览器有IE5.5+、opera 11.5+、chrome、safari 5.1+

DOMFocusIn和DOMFocusOut只有Opera支持,这里就不介绍。

当焦点从页面中的一个元素移动到另一个元素时,会依次触发下列事件:

  • focusout在失去焦点的元素中触发
  • focusin在获得焦点的元素中触发
  • blur在失去焦点的元素上触发
  • focus在获得焦点的元素中触发

3. 鼠标与滚轮事件

鼠标事件是Web开发中最常用的一类事件,常见的鼠标事件有:

  • click:在用户单击鼠标按钮或者按下回车键时触发。
  • dbclick:在用户双击鼠标按钮时触发,在DOM3级事件纳入了标准。
  • mousedown:在用户按下了任意鼠标按钮时触发。
  • mouseenter:在鼠标光标从元素外部首次移动到元素范围之内触发,这个事件不冒泡,而且在光标移动到后代元素上不会触发。
  • mouseleave: