前端开发第6篇:JavaScript客户端(浏览器)

Posted 天帅的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端开发第6篇:JavaScript客户端(浏览器)相关的知识,希望对你有一定的参考价值。

Web浏览器中的javascript

客户端JavaScript时间线

1、Web浏览器创建Document对象,并且开始解析web页面,解析html元素和它门的文本内容后添加Element对象和Text节点到文档中。在这个阶段Document.readystate属性的值是“loading”

2、当HTML解析器遇到没有async和defer属性的<script>元素时,它把这些元素添加到文档中,然后执行内火外部脚本。这些脚本会同步执行,并且在脚本下载(如果需要)和执行时解析器会暂停,因为JavaScript是单线程的。这样脚本就可以用Document.write()来吧文本插入到输入流中。解析器恢复时这些文本会成为文档的一部分。同步脚本经常简单定义函数和注册后面试用的注册事件处理程序,但它们可以遍历和操作文档书,因为它们执行时已经存在了。

3、解析器遇到了设置了async属性的<script>元素时,它开始下载脚本,并继续解析文档。脚本在它下载完成后尽快执行,但是解析器没有停下来等它下载,异步脚本禁止使用document.write()方法。

4、当文档完成解析,document.readyState属性变成“interactive”

5、所有defer属性的脚本,会按照它们在文档里的出现顺序执行。异步脚本可能也会在这个时间执行,延迟脚本能访问完成的文档书,禁止使用document.write()

6、浏览器在Document对象上触发DOMContentLoaded事件,这标志着程序执行从同步脚本执行阶段转换到异步事件驱动时间阶段。但是要注意,这时可能还有异步脚本没有执行完。

7、这时,文档已经完全解析完成,但是浏览器还在等待其他内容载入,如图片。当所有的内容完成载入时,并且所有异步脚本载入和执行,document.readyState属性改变为"complete",Web浏览器触发Windows对象上的load事件。

8、从此刻起,会调用异步事件,以异步响应用户输入事件、网络事件、计时器过期等

以上为一条理想的时间线,但是并不是所有的浏览器都支持并完成了全部细节但是大部分都支持

JavaScript不能做什么

1、JavaScript程序可以打开一个新的浏览器窗口,但是为了防止广告商滥用弹出窗口,很多浏览器限制了这个功能,是的只有为了响应鼠标单击这样的用户触发时间的时候才能使用它

2、JavaScript程序可以关闭自己打开的浏览器窗口,但是不允许它不经过用户确认就关闭其他的窗口

3、HTML FileUpload元素的value属性是只读的,如果可以设置这个属性,脚本就能设置它为任意期望的文件名,从而导致表单上传指定文件(比如密码文件)的内容到服务器

4、脚本不能读取从不同服务器载入的文档内容,除非这个就是包含改脚本。这个就防止来自其他不同服务器上的文档时间监听器,防止窃取用户输入,这个限制叫同源策略

 

同源策略及其规避方法

1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。

最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"。

  • 协议相同
  • 域名相同
  • 端口相同

 举例来说,http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。它的同源情况如下。

  • http://www.example.com/dir2/other.html:同源
  • http://example.com/dir/other.html:不同源(域名不同)
  • http://v2.www.example.com/dir/other.html:不同源(域名不同)
  • http://www.example.com:81/dir/other.html:不同源(端口不同)

同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?

很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。

  • Cookie、LocalStorage 和 IndexDB 无法读取。
  • DOM 无法获得。
  • AJAX 请求不能发送。

Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。但是,两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享 Cookie。

举例来说,A网页是http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,那么只要设置相同的document.domain,两个网页就可以共享Cookie。

 

Ajax

同源政策规定,AJAX请求只能发给同源的网址,否则就报错。

除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制。

  • JSONP
  • WebSocket
  • CORS

 

同源政策规定,AJAX请求只能发给同源的网址,否则就报错。举个例子:

我现在起了两个Django: 127.0.0.1:8000   另一个Django:127.0.0.1:8001 端口不同也是跨域操作

在127.0.0.1:8000 上使用Ajax访问127.0.0.1:8001的时候就会提示报错

        $.ajax({
            url: "http://127.0.0.1:8001/test_json",
            async : false,
            type: \'GET\',
            dataType: \'json\',
            success: function(data){console.log(\'success\', data)},
            error: function (data) {console.log(\'error\', data)}
        })

如何解决?

Web页面上调用js文件时则不受是否跨域的影响,而且拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>,这时候,聪明的程序猿就想到了变通的方法,如果要进行跨域请求, 通过使用html的script标记来进行跨域请求,动态生成<script>标签称之为:JSONP(JSON with Padding)

JSONP(JSONP - JSON with Padding是JSON的一种“使用模式”),利用script标签的src属性(浏览器允许script标签跨域),通过动态创建一个script标签,指定src属性为跨域的api,那么html会把返回的字符创当作javascript代码来进行解析,如果我们在返回的字符串中使用自定义函数形式包装起来,然后在html中调用自定义函数,即可拿到返回的字符串
 
客户端:127.0.0.1:8000
    <script>
        // 设置回调函数
        var callbackHandler = function(data){
            console.log("服务端返回的数据是:", data);
        };

        function getContent(){
        // 跨域访问的API 并指定回调函数
        var url = "http://127.0.0.1:8001/test_json?callback=callbackHandler";  //
        // 创建script标签,并设置其属性
        var script = document.createElement(\'script\');
        script.setAttribute(\'src\', url);
        // 把script标签加入head,此时调用开始
        document.getElementsByTagName(\'head\')[0].appendChild(script);
        }

    </script>

动态生成<script>标签并指定回调函数,这样就可以跨域请求API了,这是一个历史遗留的BUG吧算是,借助src的跨域特性模拟请求

服务端127.0.0.1:8001

def test_jsonp(request):
    print("请求方法为:", request.method)  # 请求方法为:GET
    func = request.GET.get(\'callback\')  # 获取回调函数
    content = \'%s(100000)\' % (func,)  # 拼接为执行 callbackHandler(100000)  
    """
    在这里我们看下我们可以在这里指定返回结果:callbackHandler(100000)
    当然也可以增加其他的内容比如: callbackHandler({"name": "shuaige", "age": 18})
    客户端接收到请求后调用回调函数并把我们放进去的数据加载上,所以使用JSONP跨域也是需要协商一下才可以
    """
    
    print("结果是:", content)  # callbackHandler(100000)
    return HttpResponse(content)  # 返回

 

梳理下步骤:

1、动态生成<script>标签封装src属性,指定API和回调函数

2、服务端接收到请求后在接收的回调函数中封装数据并返回(这里就明确了并不是你使用了jsonp的方式就可可以了,而是需要与服务器进行协商回调函数才可以)

3、通过回调函数和服务端封装返回的数据执行回调函数

 

jQuery已经帮我们封装好了的jsonp,Server端不变来看如何使用jQuery发送jsonp请求
    <script>
        // 设置回调函数
        var callbackHandler = function(data){
            console.log("服务端返回的数据是:", data);
        };

        function getContent(){
            $.ajax({
                url: "http://127.0.0.1:8001/test_json",
                type: \'GET\',
                dataType: \'jsonp\',  // 数据格式为jsonp
                jsonp: \'callback\',  // 发送给服务端的回调函数变量名
                jsonpCallback: \'callbackHandler\'  // 发送给服务端的回调函树的函数名称
                // jsonp: \'callback\', jsonpCallback: \'callbackHandler\' 类似 {"callback": "callbackHandler"}
            })
        }

    </script>

 

WebSocket  和 CORS 后续补充

Windows对象

先看看整个浏览器架构是什么样的,浏览器实现了JavaScript的规范可以解析JavaScript并通过JavaScript进行管理  好奇发展的话:可以看  http://www.cnblogs.com/luotianshuai/p/7504347.html

windows对象包含文档对象:Document 它主要处理页面    其他的windows大多是对浏览器级别的操作,可以先这么理解,在浏览器大战期间国际组织对各大浏览器共有的操作标准document页面操作进行了标准化:DOM 它是一个标准

知道它们之间的关系后继续看windows吧

计时器

setTimeout()和setInterval()可以用来注册在指定的时间之后单词或重复调用的函数,虽然他是windows对象的方法但是不会对窗口做什么事情。

setTimeout()方法用来实现一个函数在指定的毫秒数之后运行

setInterval()和steTimeout一样,只不过这个函数会在指定的毫秒数的间隔里重复调用

/*
function invoke(f, start, interval, end) {
    if (!start) start = 0;
    if (arguments.length <= 2){
        setTimeout(f, start)
    } else{
      setTimeout(repeat, start);  // 在若干毫秒后调用repeat
      function repeat() {
          let h = setInterval(f, interval);  //循环调用f()  间隔interval秒调用一次f
          // 在end毫秒后停止调用,前提是end定义了
          if (end) setTimeout(function () { clearInterval(h);}, end)
      }
    }
}
function sayHello() {
    console.log("Hello World")
}

invoke(sayHello, 10000, 66, 100);

*/
function sayHello() {
    console.log("Hello World")
}

function clearIntervalFunc(obj) {
    clearInterval(obj)
}

setTimeout(sayHello, 1000); // 在第10秒后调用一次sayHello函数
let sayHelloObject =  setInterval(sayHello, 1000); // 每隔10秒调用一次sayHello 函数
setTimeout(clearIntervalFunc,  10000, sayHelloObject);  // 10秒之后清掉函数

浏览器定位和导航

window对象的location属性引用的是Location对象,Document的location属性也是引用的Location对象。它表示该窗口显示文档的URL,并定义了方法来使窗口载入新文档。

Location对象的href属性返回的是当前URL的字符串

window.location.href
"https://www.sogou.com/web?query=%E6%94%AF%E4%BB%98%E5%AE%9D&_asf=www.sogou.…505872944052%2C1505872944707&sugsuv=1497014300786074&sugtime=1505872945685"

Location对象的其他属性:protocal, host, hostname, port, pathname 和search,分别表示URL的各个部分,它们称之为"URL分解" 属性

在这些属性中:hash和search属性比较有趣,hash返回片段标识符如果有的话(片段标识符也就是锚点),search就是URL问号部分来看

window.location.search
"?query=%E5%B8%85%E5%93%A5&ie=utf8&_ast=1505873792&_asf=null&w=01029901&p=40040100&dp=1&cid=&cid=&s_from=result_up&sut=3003&sst..........300786074&sugtime=1505873945616"

 

解析URL参数实例

function urlArgs() {
    let args = {};  // 创建一个对象
    let query = location.search.substring(1);  // 查找查询次并去掉第一个"?"问号
    let pairs = query.split(\'&\');  // 通过&分割为一个数组
    for (let i =0; i < pairs.length; i++ ){  // 循环
        let pos = pairs[i].indexOf(\'=\');  // 找到每个数组元素字符串=的下标
        if (pos === -1) continue;
        let name = pairs[i].substring(0, pos);  // 如果能找到=那就分割name为小标0到=值
        let value = pairs[i].substring(pos+1);  // 取出后面的值
        value = decodeURIComponent(value);  // 对value进行解码
        args[name] = value;  // 存储为属性
    }
    return args
}

载入新文档

Location对象的assign()方法可以使窗口载入并显示你指定的URL中的文档,replace()方法也类似但是他会删除历史记录(意思就是你不能用返回键返回上一次访问的历史网页)

location = "http://www.sogou.com";  // 跳转到搜狗
locaiton = "page2.html";  //跳转到这个页面
location = "#top";  // 跳转到文档顶部

浏览历史

Windows对象的history对象引用的是该窗口的History对象,history的back()和forward()方法与浏览器的后退和前进一样 NICE,还有一个方法go接收一个正负数,来进行前进和后退

window.history.go(-3);  // 后退3个历史记录
window.history.back();  // 后退一个历史记录 
window.history.forward();  // 前进一个历史记录

浏览器和屏幕信息

window对象的Navigator属性引用包含了浏览器厂商和版本信息的Navigator对象,Navigator对象的命名是为了纪念Netscape之后的Navigator浏览器

window.navigator.appName  // Web浏览器全称微软的是Microsoft Internet Explorer,其他厂商了为了兼容现存的浏览器嗅探一般都是Netscape
"Netscape"

window.navigator.appVersion  // 查看浏览器版本
"5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"

window.navigator.userAgent  // 浏览器在它的USER-AGENT http头部中发送的字符串
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"

/* 
userAgent 包含appVersion中所有的内容,并也可能包含其他细节,因为信息比较全,浏览器嗅探代码通常用它来嗅探
*/

window.navigator.platform  //浏览器运行在哪个系统上
"Win32"


window.navigator.onLine  // 表示浏览器是否联网 0 0 
true

screen对象属性引用的是Screen对象。它提供有关窗口显示的大小和可用的颜色数量信息。属性width和height指定的是以 项数为单位的窗口大小。属性availwidth和availheight指定的是实际可用的显示大小

screen属性和引用screen都是非标准实现的可以通过其判断是否在小屏幕上运行

对话框

windows对象提供了3个方法alert() 向用户提示一条消息等待用户关闭对话框  / confirm()也是显示一条消息,要求用户点击“确定”或“取消”按钮并返回一个布尔值

prompt()同样也是显示一条消息,等待用户输入字符串并返回字符串,还有一个showModalDialog()有用的吗?

作为Windows对象属性的文档元素

如果在HTML文档中用id属性来为元素命名,并且如果Window对象没有此名字的属性,Window对象会赋予一个属性,他的名字是id属性的值,而他们的值指向表示文档元素的HTMLElement对象

举个例子来说如果文档包含<button id="okay">元素,可以通过全局变量okay来引用此元素。但是如果window已经有了这个属性就不可以了,元素id作为全局变量的隐式应用是Web浏览器演化过程中遗留的怪癖。他主要是出于与已有Web页面向后兼容考虑的,所以不建议使用这种方法,推荐用document.getElementByID()来显示查找元素,后面会学到更简单的jQuery,来获取元素

多窗口和窗体

Window对象的open()方法可以打开一个新的浏览器窗口(或标签页,这通常和浏览器配置选项有关),它有4个可选的参数

第一个参数:是显示文档的URL如果为空打开一个空白页URL about: blank

第二个参数:窗口的名字

第三个参数:窗口属性参数  window.open("http://sogou.com", "搜狗", "width=400,height=400,status=yes,resizabel=yes")

第四个参数:一般与第二参数同时使用,如果窗口已经存在还是新窗口

 

关闭也很简单window.close

脚本化文档

客户端JavaScript的存在使静态HTML页面文档变成了交互式的WEB应用。脚本化WEB页面内容是JavaScript核心目标

脚本化可以使 宿主 程序具有 脚本 所描述的能力,比如流行在 DHTML 页面中的 JavaScript 技术,JavaScript 可以让原本是静态的 HTML 代码的页面“活”起来,具有动画,局部刷新等更高级的功能。应用程序一般是以二进制的形式发布的,用户很难根据自己的需求对其进行定制,当然,修改配置文件是一种方式,但是不够灵活。而脚本化则是通过用户自己设计脚本(程序代码 ),然后将其 注入 到应用中,使得应用的行为得到改变。

window包含一个document属性应用了Document对象,Document对象表示窗口内容 它是一个浏览器对外提供的一个巨大的操作文档内容的API,叫做文档对象模型(Document Object Model, DOM)它代表操作文档的内容

选取文档元素

通过id获取元素

// 通过id获取元素
let selection =document.getElementById("selection");
// 通过元素name属性获取元素
let radibuttons = document.getElementsByName("favorite_color");
// 通过标签获取元素
let spans = document.getElementsByTagName("span");  // 返回的是一个NodeList对象
// 通过Css 类 class获取
let log = document.getElementsByClassName("log");  // 获取包含log CSS类的元素
let fatal = document.getElementsByClassName("fatal error");  // 获取fatal Css类中包含子类error的元素

作为节点树的文档

Document对象、它的Element对象和文档中表示文本的Text对象都是Node对象。Node定义了一下重要属性:

  • parentNode:该节点的父节点,或者针对类似Document对象应该是null,因为它没有父节点
  • childNodes:只读的类数组对象(NodeList对象),它是该节点的子节点的实时表示
  • firstChild、lastChild: 该节点的子节点中的第一个和最后一个元素,如果该节点没有子节点则为null
  • nextsibling、previoursSibling该节点的兄弟节点中的前一个和下一个
  • nodeType:该节点类型9代表Document节点,1代表Element节点,3代表Text节点,8代表Coment节点11代表DocumentFragment节点
  • nodeValue:Text节点或Comment节点的文本内容
  • nodeName:元素的标签名,以大写形式表示

 属性

每个元素都是一个Node节点这个搞明白之后在就是,每个元素的属性通过结构化文档之后每个元素都是一个JavaScript对象里面的Css和src都是对象的一个属性key=value的值而已,搞明白这个旅顺前后就会通透多了

获取元素后在获取属性

let image = document.images[0];  // 获取第一个元素
let widt = parseInt(image.getAttribute("width"));  // 从元素对象中获取属性
image.setAttribute("class", "shuaige");  // 在元素对象中添加属性

既然是对象当然也可以通过对象的方式获取

document.body.attributes[0]  // <body>元素的第一个属性
document.body.attributes.bgcolor  // <body> 元素的bgcolor属性
document.body.attributes[\'ONLOAD\']  // <body>元素的onload属性

文本

let fristH1 = document.getElementsByTagName("h1")[0];  // 获取第一个H1标签
let fristChildH1 = fristH1.children[0];  // 获取H1标签的第一个元素
/*
fristChildH1.textContent  // 输出他的内容
<a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/luotianshuai/">Mr.心弦</a>
*/

创建删除节点

创建node通过

let s = document.createElement("script");  // 创建一个<script>元素
s.src = "http://sogou.com";   // 设置它的src属性值
// 然后通过append添加元素或者插入元素

创建文本node节点通过  document.createTextNode("<h1>帅哥</h1>")

 

fristClass1.appendChild(document.createTextNode("<h1>帅哥</h1>"))

 

添加元素

// 获取第一个应用了 class = day的元素
let fristDiv = document.getElementsByClassName("day")[0];
// 创建一个元素
let shuai = document.createElement("h1");
shuai.textContent= \'大帅哥\';
// 添加元素通过appendChild
fristDiv.appendChild(shuai);

// ------------------------------------------------------------------------------

let fristDiv = document.getElementsByClassName("day")[0];
let shuai = document.createElement("h1");
shuai.textContent= \'大帅哥\';


fristDiv.insertBefore(shuai, null) // 它接收两个参数第一个参数是待被插入的node节点,如果第二个参数为null,则类似appendChild

// 如果指定了第二个参数(为node对象)则会在它前面插入
fristDivChild = fristDiv.children[0];

// 插在第一个元素前面
fristDiv.insertBefore(shuai, fristDivChild); 

注:这里如果将要被添加的元素已经存在了,就类似于remove操作,且如果被添加的元素在将要被添加的元素位置已经存在那么就会重新添加一次覆盖原有的,这里是对象相同,如果对象不相同不会覆盖

删除和替换节点

fristDiv.remove();  // 删除自己的node对象
fristDiv.appendChild(shuai);  // 删除自己的儿子对象

// --------------------------------------------------------------------
// 获取第一个div元素
let fristDiv = document.getElementsByClassName("day")[0];
// 获取第一孩子元素
fristDivChild = fristDiv.children[0]
// 创建一个新node对象,也就是元素
createH1 = document.createElement("h1");
// 给node对象添加textContent属性和值
createH1.textContent = \'大帅哥\';  

// 替换
fristDiv.replaceChild(createH1, fristDivChild);  // 接收两个参数第一个参数是新元素,第二个元素是要被替换的元素

文档滚动条和窗口

把窗口比作一个X,Y轴的坐标来体现

获取其滚动条位置:

X轴为从左到右的轴值,Y轴为从上到下的轴值

window.pageXOffset
0
window.pageYOffset
0

查询窗口尺寸

window.innerHeight;
426
window.innerWidth
1920
window.innerHeight;
581

获取某个元素的坐标值

tag.getBoundingClientRect();
ClientRect {top: 86, right: 503.03125, bottom: 127, left: 438.03125, width: 65…}  // 上下左右,这个对比值是离windows窗口的上下左右值

滚动

scrollby()   scroll()   scrollTo()  就是根据上面的坐标进行滚动,我们可以接收一个函数

脚本化CSS和脚本化文档类似

JavaScript事件

客户端JavaScript程序采用了异步事件驱动编程模型。在这种程序设计风格下,当文档、浏览器、元素或与之相关的对象发生某些有趣的事情时,Web浏览器就会产生事件(event)

事件本身不是一个不需要定义的技术名词,且不是JavaScript对象,不会出现在程序源码中,当然,会有一些事件相关的对象出现在源码中

事件类型(event type):是一个用来说明发生了什么类型事件的字符串。 比如“mousemove” 表示用户移动鼠标

事件目标(event target):是发生的事件阈值相关的对象。  当事件发生时我们比如致命类型和目标   ,例如window 上的load事件或<button>元素的Click事件。

事件处理程序(event handler)或事件监听程序(event listener)是处理货响应时间函数。应用程序通过致命时间类型和时间目标,在Web浏览器中注册它们的时间处理程序函数

事件对象(evnet object):是与特定时间相关且包含有关该事件详细信息的对象。时间对象作为参数传递给时间处理程序。所有事件对象都有用来指定时间类型的type属性和指定时间目标的target属性。

事件传播(event propagation):是浏览器决定那个对象触发其时间处理程序的过程。

接下来看看下面事件

  • 文档加载和准备就绪事件
  • 鼠标事件
  • 鼠标滚轮事件
  • 键盘事件
  • 文本输入事件

事件类型

事件类型可以分成以下几类,了解这些分类有助于理解和组织长长的事件列表

依赖于设备的输入事件

有些事件和特定输入输出设备直接相关,比如鼠标和键盘包括:

"mousedown"、"mousemove"、"mouseup"、"keydown"、"keypress"和"keyup"这一样传统的事件类型,也包括像"touchmove"和"geturechange"这样新的触摸事件类型

独立于设备的输入事件

有写输入事件没有直接指定相关的特定输入设备。例如,click事件表示激活了链接、按钮或其他文档元素,这通常是通过鼠标单击事件,但也能通过键盘或触摸板事件。

用户界面事件

用户页面事件是比较高级的事件,通常出现在定义Web应用用户界面的HTML表单元素上。包括文本输入域获取键盘焦点的focus事件、用户改变表单元素显示值的change事件和用户点击表单的“提交”按钮的submit事件

状态变化事件

有写事件不是由用户活动而是由网络或浏览器活动出发,用来表示某种声明周期或相关状态的变化。当文档完全加载时,在Window对象上会发生load事件,这可能是这类事件最常用的

特定API事件

HTML5及相关规范定义了大量的Web API都有自己的事件类型。拖放API定义了诸如“dragstart”、“dragenter”、“dragover”和“drop”事件,应用程序向自定义拖放源(drag source)或拖放目标(drop target)就必须处理这些相关事件。HTML5的<video>和<audio>元素定义了一长串想"wating"、"playing"、"seeking" 和“volumecacheng”等相关事件

计时器和错误处理程序

计时器(timer)和错误处理程序(error handler)

传统事件类型

表单事件

表单在浏览器早期的时候对<form>表单支持算是最好的,当提交表单和重置表单的时候分别会触发submit和reset事件。包括用户在点击复选框会触发click事件输入文字会触发input事件等

window事件

window事件是指事件的发生与浏览器本身而非窗口显示的任何特定文档内容先关。但是,这些事件中有一些会和文档元素上发生的事件同名

load事件:是这些事件中最重要的,当文档和其他所有外部资源(比如图片)完全加载并显示给用户时就会触发

unload事件:和load相对,当用户离开当前文档转向其他文档时会触发它,unload事件处理程序可以用于保存用户的状态,但他不能用于取消用户转向其他地方

beforunload事件:的处理程序返回字符串,那么在新页面加载钱,字符串会展示给用户对话框上用户就有机会取消跳转

<img>元素这样的单个文档元素也能为load和error事件注册处理程序

鼠标事件、键盘事件这俩事件很常用

鼠标事件因为太频繁,所以一定不要用它处理密集运算,键盘和鼠标都有一个up和down的事件活用

注册事件处理程序

注册事件处理程序最简单的方式就是通过设置事件目标的属性为所需事件处理程序的函数,按照约定,事件处理程序属性的名字有“on”后面跟着事件名组成:onclick、onchange、onload、onmouseover等,注意这些属性名是区分大消息的所以都是消息

// 设置window对象的unload属性为一个函数
// 该函数是事件处理程序:当文档加载完毕时调用它
window.onload = function () {
    // 查找一个<form>元素
    let elt = document.getElementById("shipping_address");
    // 注册事件处理程序函数
    // 在表单提交前调用它
    elt.onsubmit = function () {return console.log(this);}
};

设置HTML标签属性为事件处理程序

<button onclick="alert(\'thank you\');">点击这里</button>

有很多事件我们可以使用

属性
此事件什么时候发生(什么时候被触发
onabort     图象的加载被中断
onblur     元素失去焦点
onchange    区域的内容被修改
onclick 当用户点击某个对象时调用的事件句柄(比点击input标签时执行上面的代码例子)
ondblclick 当用户双击某个对象时调用的事件句柄
onerror   在加载文档或图像时发生错误
onfocus 元素获得焦点
onkeydown 某个键盘按键被按下
onkeypress 某个键盘按键被按下并松开
onkeyup 某个键盘被松开
onload 一张页面或一副图片完成加载
onmousedown 鼠标按钮被按下 
onmousemove 鼠标移动过来后
onmouseout 鼠标从某个元素移开
onmouseover 鼠标移动到某个元素之上
onmouseup 鼠标按键被松开
onreset   重置按钮被点击
onresize  窗口或框架被重新调整大小
onselect  文本被选中
onsubmit  确认按钮被点击
onunload  用户退出页面

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

当指定了一串JavaScript代码作为HTML事件处理程序属性的值时,浏览器会把代码串传唤为类似下面的函数中

function (event) {
    with (document){
        with (this.form || {}){
            with (this){
                /* 这里是编码*/
            }
        }
    }
};

 

1)简要说明  
       with 语句可以方便地用来引用某个特定对象中已有的属性,但是不能用来给对象添加属性。要给对象创建新的属性,必须明确地引用该对象。  

2)语法格式  
with(object instance)  
{  
        //代码块  
}  
       有时候,我在一个程序代码中,多次需要使用某对象的属性或方法,照以前的写法,都是通过:对象.属性或者对象.方法这样的方式来分别获得该对象的属性和方法,着实有点麻烦,学习了with语句后,可以通过类似如下的方式来实现:  
with(objInstance)  
{  
       var str = 属性1;  
.....  
} 去除了多次写对象名的麻烦。  

addEventListener()

任何能称为事件目标的对象-这些对象包括window对象、document对象和所有文档元素,都定义了一个名叫addEVentListener()方法,这个方法接收三个参数:

第一个参数是:什么时候触发也就是事件名称比如:click   它不应该用户设置事件处理程序属性的前缀"on"

第二个参数是:触发事件之后对应的处理函数

第三个参数是:布尔值true/false 如果为True的情况下不予其他事件并行,如果为false的时候就可以与其他并行

这里可以通过addEventListener()注册多个相同事件,但是如果参数相同的话只调用一次

相对应addEventListener()的是removeEventListener()方法,它同样有三个参数,从对象中删除事件处理程序函数而非添加,它常用于临时注册事件处理程序,然后不久后就删除它

document.removeEventListener("mousemove", handleMouseMove, true);

事件调用顺序

通过设置对象属性或HTML属性注册的处理程序一直优先调用

通过addEventListener()注册的处理程序按照他们注册顺序调用

通过attachEvent()注册的处理程序可能按照任何顺序调用,所以代码不应该以来与调用顺序

事件冒泡和绑定

    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>


/*
冒泡:
    看上面的ul元素,如果我想给每个li添加事件怎么办?比如添加click事件
    每个都加上?
    这个冒泡的作用就体现出来了,我在ul里加上一个事件,如果是冒泡规则的话,当我们点击li的时候就会往父级元素找事件
    如果父级Ul存在一个事件$ul.click(){}  这里默认第一个参数为event事件的.target属性找到其子元素也就是li
    我们就可以通过这个进行操作了

    冒泡可以说是从内到外

绑定也是同理从外到内
*/

jQuery

jQuery4种不同的调用方式

1. 传递css选择器给$(),选择器
$("div>p")
第二个参数,元素起始点

2. 传递HTML文本字符串给$(),将创建好的HTML元素封装到jQuery对象
$("<image/>")
第二个参数,给元素属性赋值
var img = $("<img/>",                            //创建一个image元素
                        {src:url,                            //定义元素属性
                        css:{borderwidth:5},
                        click:check)
                        });

3. Element、Document、window对象给$(),一些特定的DOM元素,如常用的DOM对象:document、location、form
$(document).find("div>p").html()); 

4. 传入一个函数给$()
$(function(){
});
复杂版:
$(document).ready(function(){
});
特殊用法:
jQuery.noConflict();        //还原$()为初始值
jQuery(function($){            //让$()成为jQuery的局部别名
});

jQuery术语

jQuery函数:

jQuery函数就是jQuery或$()的值,该函数可以用来创建jQuery对象,用来注册DOM就绪时需要调用的处理陈故乡,还用做jQuery命令空间,通常用$()来引用。他可以用来做命名空间,因此jQuery函数也可以称之为“全局jQuery对象”,但不要和“jQuery对象”混淆

jQuery对象:

jQuery对象是由jQuery函数返回的对象。一个jQuery对象表示一组文档元素,也叫作“jQuery结果”、“jQuery集”或“包装集”

选中元素:

传递给jQuery的选择器

jQuery方法:

jQuery方法是由jQuery函数返回的jQuery对象的方法。jQuery类库做重要的部分就是它定义的这些强大的方法。

jQuery的getter和setter

1、jQuery使用同一个方法既当getter用有来做setter用,而不是定义一对方法。如果传入一个新值给该方法,则它设置此值;如果没指定值吗,则返回当前值

2、用作setter时,这些方法会给jQuery对象中的每一个元素设置值,然后返回jQuery对象以方便链式调用。

3、用作getter时,这些方法只会查询元素集中的第一个元素,返回单个值,getter不会返回调用自身的jQuery对象,因此他只能出现在链式调用的末尾

4、用作setter时,这些方法经常接受对象参数,在这种情况下,该对象的每一个属性都指定一个需要设置的名/值对

5、用作setter时,这些方法经常接受函数参数,在这种情况下,会调用该函数来计算需要设置的值。调用该函数时的this值是对应的元素,第一个参数是钙元素的索引值,当前置则作为第二个参数传入

获取和设置HTML属性

    <script>
        $("form").attr("action");  // 获取第一个form元素的action属性
        $("#icon").attr("src", "icon.gif");  // 设置src属性
        $("#banner").attr({  // 一次性设置4个属性
            src:"icon.gif",
            alt:"advertisement",
            width:720, height:64
        });
        $("a").attr("target", "_blank");  // 使所有的链接在新窗口中打开
        $("a").attr("target", function () {
            // 使用setter时this值是对应的元素
            if (this.host === location.host){return "_self"
            }else{
                return "_blank"
            }
        });
        $("a").remove("target");  // 删除元素的target属性
    </script>

获取或设置css属性 

    <script>
        $("h1").css("font-weight");  // 获取第一个<h1>元素的字体属性
        $("h1").css("fontWeight");  // 也可以采用驼峰式建议使用-
        $("h1").css("font");  // 错误不可以获取符合样式
        $("h1").css("font-variant", "smallcaps");  // 将样式设置在所有<h1>元素上
        $("div .note").css("border", "solid black 2px");  // 设置符合样式是OK的
        $("h1").css({backgroundColor: "black", padding: "10px 2px 4px 20px"});  // 一次性设置多个样式,且可以使用驼峰式
        // 让所有标签<h1>的字体增大25%
        $("h1").css("font-size", function (i, curval) {
            // 这里i是数组对象的下标值, curval 是当前对象的font-size的值
            return Math.round(1.25 * parseInt(curval))
        })
    </script>

获取和设置css类

    <script>
        // 添加
        $("h1").addClass("hilite");  // 给所有的h1元素添加一个类
        $("h1+p").addClass("hilite first");  // 给<h1>后面的<p>添加两个类
        $("section").addClass(function(n){  // 传递一个函数用来给匹配的每一个元素添加自定义类
            return "

以上是关于前端开发第6篇:JavaScript客户端(浏览器)的主要内容,如果未能解决你的问题,请参考以下文章

java复习前端篇——JavaScript

前端开发之JavaScript基础篇一

前端知识杂烩(Javascript篇)

测试开发专题-目录

javascript之基础篇

第1719期简明 JavaScript 函数式编程-入门篇