zoukankan      html  css  js  c++  java
  • 前端开发【第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,  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:{border5},
                            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",
                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 "section" + n ;
            });
            // 删除
            $("p").removeClass("hilite");  // 从所有的<p>元素中删除一个类
            $("p").removeClass("hilite first");  // 从所有的<p>元素中删除2个类
            $("section").removeClass(function(n){  // 传递一个函数用来给匹配的每一个元素删除自定义类
                return "section" + n ;
            });
    
            // 切换css类
            $("#box").toggleClass("box2");  // 切换CSS类如果不存在则添加
            $("#box").toggleClass(function (n) {  // 切换用函数计算出来的类
                return "big bold h1-" +n ;
            });
            $("box").toggleClass("hilite", true);  // 类似于addClass
            $("box").toggleClass("hilite", false);  // 类似于removeClass
    
            // 检测css类
            $("box").hasClass("first");  // 是否所有box元素都有改类
            $("box").is("first");  // 功能和上线类似
            $("box").is("first secede");  // is()比hasClass()更灵活
        </script>

    在写一个更换clss的小例子

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style type="text/css">
            .box1 {
                background-color: red;
                height: 100px;
    
            }
            .box2 {
                background-color: blueviolet;
                height: 1000px;
            }
        </style>
    </head>
    <body>
        <div id="box">
            shuaige
        </div>
        <script type="text/javascript" src="jquery-2.1.4.min.js"></script>
        <script type="text/javascript">
            $(function () {
                let boxObject = $("#box");
                boxObject.addClass("box1")
            });
    
            $("#box").bind("click", function () {
                // 转换类,好玩
                $(this).toggleClass("box2")
            })
        </script>
    </body>
    </html>

    设置和获取元素内容

    text和html方法用来获取和设置元素的文本内容或HTML内容。

    当不带任何参数的时候:text()方法将获取所有匹配的文本内容,html()方法将获取所有匹配的第一个元素的HTML内容

     和其他setter方法一样,我们还可以传入函数

            $("h1").text(function (n, current) {  // 给每一个标题添加章节号
                // n 为当前数组元素的下标    current为当前元素的text内容
                return n + current
            });
    
            $("h1").html(function (n, current) {  // 给每一个标题添加章节号
                // n 为当前数组元素的下标    current为当前元素的text内容
                return n + current
            })

    获取和设置元素的位置高度

    使用offset()方法可以获取或设置元素的位置。该方法相对文档来计算位置的值,返回一个对象,带有left和top属性,用来表示X和Y坐标。如果传入带有这些属性的对象给该方法,它会给元素设置指定的位置。在有必要时,会设置CSS的position属性来使得元素可定位

    修改文档结构

    HTML文档表示为一颗节点树,而不是一个字符串的线性顺序,因此插入、删除、替换操作不会像操作字符串和数组一键更简单

    插入和替换元素

    根据调用的方法不同,会在选中元素的(里面、前面、后面)插入内容。如果带插入的内容已经存在文档的元素,会从当前位置移走它。如果他需要插入多次,在必要时恢复至钙元素

    <script>
            $("#log").append("<br/>" + message);  // 在#log元素的内部尾部增加新内容
            $("h1").prepend("shuai");   // 在每个<h1>的元素的内部的起始处添加章节标识
            $("h1").before("<hr/>");  // 在每个<h1>的前面添加水平线
            $("h1").after("<hr/>");  // 在每个<h1>后面添加水平线
            $("hr").replaceWith("<br/>");  // 替换<hr/>元素为<br/>元素
            // 将h2替换为h1,保持内容不变
            $("h2").each(function () {
                let h2 = $(this); // this代表循环的当前对象
                h2.replaceWith("<h1>" + h2.html() + "</h1>");
            });
            // 这是给每个<h1>的开头添加文章标识的另一种方法
            $("h1").map(function () { return this.firstChild;}).before("帅")
    
        </script>

    复制元素

        <script>
            // 通过方法clone来复制元素
            // 添加一个以"linklist" id的div
            $(document.body).append("<div id='linklist'<h1>list of Links</h1></div>");
            // 建文档中的所有链接赋值并插入新的div中
            $("a").clone().appendTo("#linklist");
            // 在每一个链接后面插入<br/>元素,使其以独立行显示
            $("#linklist > a").after("<br/>")
            /*
            clone()不会赋值事件处理程序和与元素相关的其他数据,如果想复制这些数据,需要传入true参数
             */
        </script>

    包装元素

    插入HTML文档的另一种类型涉及在一个或多个元素中包装新元素,jQuery定义了3个包装函数:

    • wrap()包装每一个选中元素
    • wrapInner()包装每一个选中元素的内容
    • wrappAll()则将选中的元素作为一组来包装

    这些方法通常传入一个新创建的包装元素或用来创建新包装元素的HTML字符串,当然字符串中可以包含多嵌套元素,如果传入的函数给这些方法,它会在每个元素的上下稳重调用一次,this同样指向钙元素。

    <script>
            // 用<i>元素包装所有的<h1>元素
            $("h1").wrap(document.createElement("i"));  // 产生<i><h1>...</h1></i>
            // 包装所有<h1>元素的内容,是用字符串穿参更简单
            $("h1").wrapInner("<i/>");  // 产生<h1><i>....</i></h1>
            // 将第一个段落包装在一个锚点的div里
            $("body>p:first").wrap("<a name='lead'><div class='first'></div></a>");
            // 将其他段落包装在另一个div里
            $("body>p:not(:first)").wrapAll("<div class='rest'></div>");
    
        </script>

    删除元素

    empty()会删除每个选中元素的子节点,但不会修改元素自身,对比而言remove()方法会从文档中溢出选中元素(以及所有元素内容),unwrap()方法可以用来实现元素移除,其方法是wrap的反操作

    jQuery事件

    简单的事件注册方法

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

    1、focus和blur事件不支持冒泡,但是focusin和focusout事件支持

    2、相反的mouseover和mouseout事件支持冒泡,但这经常不方便,因为很难知道鼠标是从自己感兴趣的元素移开了,还是从改元素的子孙元素移开了,mouseenter和mouseleave是非冒泡事件,这可以解决上面的问题

    3、resize和unload事件类型只在Window对象中触发,如果想要给这两个事件类型注册处理程序,应该在$(window)上调用他们

    4、toggle()该方法将事件处理程序函数绑定到单击事件,可以指定两个或多个处理程序函数,当点击事件发生时,jQuery每次会调用一个处理程序函数。例如,如果调用toggle(f,g,h),第一次单击事件触发时,会调用函数f(),第二次g(),第三次h()

    5、可以通过HTML字符串给$()方法来创建该字符串所描述的元素,还可以传入一个对象(当做第二个参数),该对象由属性组成。如果第二个参数属性中有如上列举的注册事件方法相同,该属性值会被当做处理程序函数,并注册为命名事件类型处理程序

            $("<img/>", {
                src: image_url,
                alt: image_description,
                className: "translucent_image",
                click: function () {
                    $(this).css("opacity", "50%");               
                }
            })

    jQuery事件处理程序

    上面的例子中事件处理程序函数当做是不带参数及不返回值的,先这样很正常。单jQuery调用每一个事件处理程序时的确传入了一个或多个参数,并且对处理程序的返回值进行了处理。

    需要知道的最重要的意见事情是,每个事件处理程序都传入了一个jQuery事件对象作为第一个参数。

    通常,调用事件处理程序时只带有事件对象这个唯一参数。如果用trigger()显示触发事件,可以传入额外的参数数组。这样做 时,这些参数会在第一个事件对象参数之后传递给事件处理程序

    不管他们如何注册的,jQuery事件处理程序函数的返回值始终有意义,当事件处理程序返回一个值时(飞undefind值)jQuery会将该值存储在Event对象的result属性中,该属性值可以被后续调用的事件处理程序访问

    jQuery事件对象

    jQuery通过定义自己的Event对象来隐藏浏览器之间的实现差异,当一个jQuery事件处理程序被调用是,总会传入一个jQuery事件对象作为其第一个参数。jQuery事件对象主要以W3C标准为基准,同事它也实现了一些实际的事件标准。jQuery会将一下所有字段从原声的Event对象中复制到jQuery Event对象上

    altKey        ctrlKey        newValue        screenX
    attrChange    currentTarget  offsetX         screenY
    attrName      detail         offsetX         shiftKey
    bubbles       eventPhase     originalTarget  srcElement
    button        fromElement    pageX           target
    cancelable    keyCode        pageY           toElement
    charCode      layerX         prevValue       view
    clientX       layerY         relatedNode     wheelDelta
    clientY       metaKey        relatedTarget   whic

    除了这些属性,Event对象还定义了以下方法

    preventDefault()            isDefaultPrevented()
    stopPropagation()           isPropagationStoppend()
    stopImmediatePropagation()  isImmediatePropagationStopped()

    事件处理程序高级注册-3.0中被删除推荐使用 on

    jQuery定义了相当多的简单的方法来注册事件处理程序。所有这些方法都是简单的调用单一的,接下来看下更复杂的bind()事件类型绑定处理程序

    该处理程序会绑定到jQuery对象中的每一个元素上。直接bind()可以让我们使用事件注册的高级特性,这些特性在较简单的方法上是不可用的。

    在最贱形式下,bind()需要一个事件类型字符串作为其第一个参数,以及一个事件处理程序作为其第二个参数。

    $('p').click(f)
    //等价于
    $('p').bind('click', f)

    调用bind()时还可以带有三个参数。在这种形势下,事件类型是第一个参数,处理程序函数是第三个参数

    bind()还有其他高级特性。如果第一个参数是由空额分割的事件类型列表,则处理程序函数回味每一个命令的事件类型注册

    $('a').hover(f)
    // 等同于
    $('a').bind('mouseenter mouseleave', f)

    bind()的另一个重要特性是允许为注册的事件处理程序制定命名空间,这使得可以定义处理程序,能方便后续触发或写在特定命令空间下的处理程序。处理程序的命名空间对于开发可服用jQuery代码的类库或模块的程序员来说特别有用。事件命名空间类似的CSS的类选择器

    // 作为mouseover处理程序在命名空间"myMod"中把f绑定到所有元素
    $('a').bind('mouseover.myMod', f)
    // 甚至还可以给处理程序分配多个命名空间,在命名空间"myMod"和"yourMod"中作为mouseout处理程序绑定f
    $('a').bind('mouseout.myMod.yourMod', f)

    bind()的最后一个特性是,第一个参数可以是对象

    // 调用$('a').hover(f, g)等价于
    $('a').bind({mouseenter:f, mouseleave:g})

    注销事件处理程序

    用bind()注册事件处理程序后,可以用unbind()来注销它

    <script>
            $('*').unbind();  // 从所有元素中溢出所有jQuery事件处理程序
            $('a').unbind("mouseover mouseout");  // 从所有a元素中取消绑定所有mouseover和mouseout处理程序
    
            // 取消bind在"myMod"命名空间下的所有mouseover和mouseout处理程序
            $('a').unbind("mouseover.myMod mouseout.myMod");
    
            // 如果想小心的取消自己绑定的事件处理程序,但没有使用命名空间,必须保留事件处理程序函数的一个引用
            // 并使用unbind()带两个参数的版本
            $('#mybutton').unbind('click', myClickHandler);
    
        </script>

    触发事件

    当用户使用鼠标、键盘或触发其他事件类型是,注册的事件处理程序就会自动调用。然而,如果能手动触发事件,有时会很有用。手动触发事件最简单的方式是不带参数调用事件注册的简单方法比如(click()或mouseover()),与很多jQuery方法可以用时做getter和setter一样,这些事件方法在带有一个参数时会注册事件处理程序,不带参数调用时 则会触发事件处理程序

    $('#my_form').submit();

    submit()方法自己合成了一个Event对象,并触发了给submit事件注册的所有事件处理程序。

    就如jQuery定义了一个通用的bind()方法一样,jQuery也定义了一个更通用的trigger()方法。通常,trigger()时会传入事件类型字符串作为第一个参数,trigger()会在jQuery对象中的所有元素上触发为该类型事件注册的所有处理程序

    $("#my_form").trigger("submit");  // 等价于上线的submit()

    如果传入的是一个普通的对象 ,会创建新的jQuery Event对象

    $('#button1').trigger({type: 'click', synthetic: true})

    如果传入第二个参数,trigger()传出的第二个参数会成为每个触发事件处理程序的第二个参数,如果传入数组作为第二个参数,数组的每一项会作为独立参数传递给触发的处理程序

            $('#button1').trigger("click", true);  // 传入单一额外参数
            $('#button1').trigger("click", [x, y, z]);  // 传入三个额外参数

    第二个参数在自定义事件中非常有用

    实时事件-推荐使用on

    bind()方法绑定事件处理程序到指定的文档,但是对于动态生成的怎么办?jQuery使用“实时事件”来解决这个问题,需要使用delegate()和undelegate()方法来替代bind()和unbind()。通常在$(document)上调用delegate()并传入一个jQuery选择器字符串、一个jQuery事件类型字符串以及一个jQuery事件处理程序函数。

    // 给按标签bind一个事件和处理程序函数
    $(document).delegate('a', 'mouseover', linkHandler)

    非常赞不需要在生成标签的时候在指定一个onclick事件了,就可以动态的进行bind了

            // 静态链接的静态事件处理程序
            $('a').bind("mouseover", linkHandler);
            // 文档中动态更新的部分使用实时事件处理程序
            $(".dynamic").delegate("a", "mouseover", linkHandler)

    动画效果

    通过CSS来产生视觉效果,例如除了让一个元素消失,还可以在半秒的时间内逐步减少opacity属性的值,使其快速淡出,而不是瞬间小时。这些视觉效果能给用户带来更愉悦的体验,jQuery使其是嫌弃来更简单

    jQuery定义了fadeIn()和fadeOut()等简单的方法来实现常见视觉效果。除了简单动画方法,jQuery还定义了一个animate()方法,用来实现更复杂的自定义动画。

    每段动画都有时长,用来指定动画效果持续多长事件。可以使用毫秒数值或字符串指定时长。字符串“fast”表示200ms。字符串“slow”表示600ms。如果指定的字符串时长jQuery无法识别, 则采用默认时长400

    ms。可以给jQuery.fx.speeds添加新的字符串到数值映射关系来定义新的时长名字:

    jQuery.fx.speeds["medium-fast"] = 300;
    jQuery.fx.speeds["medium-slow"] = 500;

    jQuery动画方法经常使用动画时长来作为可选的第一个参数。如果省略时长参数,通常会得到默认的值400ms

            $("#message").fadeIn();        // 使用淡入效果显示元素,持续400ms
            $("#message").fadeOut("fast"); // 使用淡出效果隐藏元素

    禁用动画

    动画很多网站上已经为了标配,但是,并不是所有的用户都喜欢;有写用户觉得动画分散注注意力,有写则感觉动画操作不便。残障用户可能会发现动画妨碍阅读,老旧设备用户则会感觉动画耗费很多CPU时间。jQuery可以非常简单的全局禁用所有动画;简单的设置jQuery.fx.off为true就好。该设置会将每段动画的时长变成0ms,这样动画看起来就像没有动画效果的立刻切换了。

            // 全局禁用动画效果,当页面设计者在页面加入带有"stopmoving"类用户点击就可以禁用动画
            $(".stopmoving").click(function () { jQuery.fx.off = true})

    jQuery动画是异步的。调用fadeIn()等动画方法时,它会立刻返回,动画则在“后台执行”。由于动画方法会在动画完成前返回,因此可以向很多jQuery动画传入第二个参数(可选),它是一个函数,会在动画完成后调用。该函数在调用时不会传入任何参数,this值就是发生动画的文档元素。

            // 用淡入效果快速显示元素,动画完成时,在元素里显示一些文字
            $("#message").fadeIn("fast", function () { $(this).text("Hello World")})

    给动画方法传入回调函数,可以在结束时执行操作。不过,如果只是想顺序执行多段动画的话,回调方式是没有必要的。jQuery动画默认是队列化的。如果一个元素已经在动画过程中,在调用一个动画方法时,新动画不会立刻执行,而是会延迟到当前动画结束后才执行。例如可以让一个元素持久显示前 ,先闪烁一阵

    $("#blinker").fadeIn(100).fadeOut(100).fadeIn(100).fadeOut(100).fadeIn();

    jQuery动画方法可以接受可选的时长和回调参数。还可以传入一个对象来调用动画方法,该对象的属性指定动画选项;

            // 将时长和回调参数作为对象属性而不是参数传入
            $("#message").fadeIn({
                duration: "fast",
                complete: function () { $(this).text("Hello World")}
            })

     使用通用的animate()方法时,经常传入选项对象作为参数,其实,这也可以用于更简单动画方法。使用选项对象可以设置更高级选项,比如控制动画的队列和欢动

    简单动画

    jQuery定义了9个简单的动画方法用来隐藏和显示元素。根据事先的动画类型,他们可以分为三组

    fadeIn()、fadeOut()、fadeTo()

    这是最简单的动画:fadeIn()和fadeOut()简单的改变了CSS的opacity属性来显示或隐藏元素。两者都可以接受可选的时长和回调参数。fadeTo()稍有不同: 它需要传入一个opacity目标值,fadeTo()会将元素的当前opacity值变化到目标值。fadeTo()会将元素的当前opacity之变化到目标值。

    show()、hide()、toggle()

    上面的fadeOut()方法可以让元素不可见,但依旧保留了元素在文档布局中的展位。hide()方法则会将元素从布局中溢出,hide()在将元素的opacity减少到0时,同时它还会将元素的宽度和高度收缩到0,show()则会做反向操作

    toggle()可以改变在上面调用它的元素的可视状态:如果隐藏则调用show(),如果现实,则调用hide()。与show()和hide()一样,必须传入时长或选项对象给toggle()来产生动画效果。给toggle()传入true和不带参数调用show()是一样的,传入了false则不带参数调用hide()是一样的,如果传入两个或多个函数参数给toggle()他会注册为事件处理程序

    slideDown()、slideUp()、slideToggle()

    slideUp()会隐藏jQuery对象中的元素,方式是将其高度动态变化到0,然后设置Css的display属性为"node"。slideDown()执行反向操作,来使得隐藏的元素再次课件。slideToggle()使用向上滑动或想下滑动动画来切换元素的可见性。

            // 用淡出效果将所有的图像隐藏,然后显示他们,接着向上滑动,再向下滑动
            $("img").fadeOut().show(300).slideUp().slideToggle();

    自定义动画

    与简单的动画方法实现的效果相比,使用animate()方法可以实现更多通用动画效果。传给animate()方法的第一个参数指定动画内容,剩余参数指定如何指定动画,第一个参数是必须的:它必须是一个对象,该对象的属性指定要变化的CSS属性和它们的目标值。animate()方法会将每个元素的这些CSS属性从初始值变化到指定的目标值,例如slideUp()效果可以用

            // 将所有的图片的高度缩小到0
            $("img").animate({height: 0})

    第二个参数是可选的,可以传入一个选项对象给animate()方法

            $("#sprite").animate({
                opacity: .25,             // 将不透明度调整为0.25
                fontSize: 10              // 将字体大小变化到10像素
            },{
                duration: 500,            // 动画持续半秒
                complete: function () {  // 在动画完成时调用该函数
                    this.text("Goodbye") // 改变元素的文本
                }
            })

    动画属性对象

    第一个参数必须是对象,该对象的属性名必须是CSS属性名

            $("p").animate({
                "margin-left": "+=.5in",// 增加段落缩进  这里JavaScript不识别以-分割的需要加引号或通过驼峰式也可以marginLeft
                opacity: "-=.1"          // 同事减少不透明度
            })

    动画选项对象

    animate()方法的第二个参数是可选的,该选项对象用来指定动画如何执行。有两个最重要的选项我们已经接触过。duration属性指定动画持续的毫秒事件,该属性的值还可以是"fast"、“slow”或任何在jQuery.fx.speeds定义的名称

    赢一个是complete属性:它指明在动画完成时的回调函数。和complete属性类似,step属性指定在动画每一步或每一帧调用的回调函数。在回调函数中,this指向在连续变化的元素,第一个参数则是正在变化的属性的当前值。

    在选项对象中,queue属性指定动画是否需要队列化---是否需要等到所有尚未发生的动画完成后执行该动画。默认情况下,所有动画都是队列化的。将queue属性设置为false可以取消队列化。非队列化的动画会立刻执行。随后队列化的动画不会等待非队列化执行完后才执行

    $("img").fadeIn(500).animate({ "+=100"}, {queue: false, duration: 1000}).fadeOut(500);

    上面的fadeIn()和fadeOut()效果是队列化的,但animate()的调用(在1000毫秒内连续改变width属性)是非队列化的。这段width动画和fadeIn()效果的开始时间相同。fadeOut()效果会在fadeIn()效果完成时立刻开始,他不会等到width动画完成。

    jQuery中的Ajax

    load()方法

    load()是所有的jQuery工具中最简单的:向它传入一个URL,他会异步加载该URL的内容,然后将内容插入每一个选中元素中,替换掉已经存在的内容:

            // 每隔60秒加载并显示公告
            setInterval(function () {$("#box").load("2-2.html")}, 6000)

    如果想加载片段的话,如果想加载文档选中部分空格必须加上

    $('#temp').load("wheather_report.html #temperature")

    load()方法还可以接受两个可选参数。第一个可选参数表示的数据可以追加到URL后面,或者与请求一起发送。如果传入的是字符串,则会追加到URL后面,通常load()方法发送HTTP GET请求,但是如果传入数据对象,则它会发送POST请求。

    $("#box").load("us_wather_report.html", {zipcode: 20134, units: "f"})
        <script>
            let box = $("#box");
            // bind click事件
            let buttonLoad = $("#btn-load");
            buttonLoad.on("click", function () {
                console.log("发送Ajex Load 请求");
                box.load("http://127.0.0.1:8000/load_api/", { sayHello: "shuaige", age: 10})
            })
    
        </script>

    如果发送的是对象,那么就是POST请求

    load()方法的另一个可选参数是回调函数

    当Ajax请求成功或未成功,以及(当请求成功时)URL加载完毕并插入选中元素时,会调用改回调函数。如果没有指定任何数据,回调函数可以作为第二个参数传入,否则,他必须是第三个参数

    jQuery对象的每一个元素上都会调用回调函数,并且每次调用都会传入三个参数:被夹在的URL的完整文本内容、状态码字符串,以及用来加载该URL的XMLHttpRequest对象。其中,状态参数是jQuery的状态码,不是HTTP的状态码,其值类似“success”, “error”和“timeout”的字符串

    可选的 callback 参数规定当 load() 方法完成后所要允许的回调函数。回调函数可以设置不同的参数:

    • responseTxt - 包含调用成功时的结果内容
    • statusTXT - 包含调用的状态
    • xhr - 包含 XMLHttpRequest 对象

    下面的例子会在 load() 方法完成后显示一个提示框。如果 load() 方法已成功,则显示“外部内容加载成功!”,而如果失败,则显示错误消息:

    $("button").click(function(){
      $("#div1").load("demo_test.txt",function(responseTxt,statusTxt,xhr){
        if(statusTxt=="success")
          alert("外部内容加载成功!");
        if(statusTxt=="error")
          alert("Error: "+xhr.status+": "+xhr.statusText);
      });
    });
    jQuery的Ajax状态码
    jQuery的所有Ajax工具,包括load()方法,会调用回调函数来提供请求成功或失败的异步消息。这些回调函数的第二个参数是一个字符串,可以取以下值
    "success":
        表示请求成功完成
    "notmodified":
        该状态码表示请求已正常完成,但服务器返回的响应内容是HTTP 304 "Not Modified", 表示请求的URL内容和上次请求的内容相同,没有变化。只有在选项中设置ifModified为true时,改状态吗才会出现. 
    jQuery1.4认为 "notmodified"状态码是成功的,但是之前的版本会将其当成错误 "error": 表示请求没有成功完成,原因是HTTP错误。更多细节,可以检查传入参数每一个回调函数中的XMLHttpRequest对象中的HTTP状态码来获取 "timeout": 如果Ajax请求没有在选定的超时事件内完成,会调用错误回调,并传入该状态码。默认情况下jQuery的Ajax请求没有超时限定,只有指定了timeout选项时才能看到该状态码 "parsererror": 该状态码表示HTTP请求已完成,但jQuery无法按照期望的方式解析。例如,如果服务器返回的是不符合格式的XML文档或者不符合格式的JSON文本时,就会出现改状态码

    jQuery.get()和jQuery.post()

    jQuery.get()使用HTTP GET请求来实现,jQuery.post()使用HTTP POST请求,其他两者则都是一样的,与jQuery.getJSON()一样,这两个方法也接受相同的三个参数:

    • 必须的URL
    • 可选的字符串或对象
    • 可选但实际总会使用的回调函数:可以传三个参数(responseTxt,statusTxt,xhr) ====== (内容, Ajax状态, XMLTttpRequest对象)

    jQuery的Ajax数据类型

    text  
        将服务器的响应作为纯文本返回不做任何处理
    html 
        和text类似:响应是纯文本。load()方法使用该类型,将返回的文本插入到文档中
    xml
        请求的URL被认为指向XML格式的数据,jQuery使用SMLHttpRequest对象的responseXML属性来替代responseText属性。传给回调函数的值是一个表示该XML文档的Document对象,而不是保存文档文本的字符串
    script
        请求的URL被认为指向JavaScript文件,返回的文本在传入回调函数前,会当做脚本执行.jQuery.getScript()使用该类型。当类型是"script"时,jQuery可以使用<script>元素来替代XMLHttpRequest对象,
    因此可以处理跨域请求。 json 请求的URL被认为指向JSON数据的数据文件。会使用jQuery.parseJSON()来解析返回的内容,的到的JSON对象后传入回调函数。jQuery.getJSON()使用该模型。如果类型是
    "json"同事URL或数据字符串含有"=?",
    该类型会转换成jsonp jsonp 请求的URL被认为指向服务器脚本,改脚本支持JSONP协议,可以将JSON格式的数据作为参数传递给客户端指定的函数,在该类型下,传递给回调函数的是解析好的对象,由于JSONP请求可以通过
    <script>元素实现,
    因此该类型可以用来做跨域请求。

    jQuery.ajax()函数

    jQuery的所有Ajax工具最后都会调用jQuery.ajax()--这是整个类库中最复杂的函数。jQuery.ajax()仅接受一个参数:一个选项对象,该对象的属性指定Ajax请求如何执行的很多细节

    例如:jQuery.getScript(url, callback) 与下面的jQuery.ajax()的调用等价

                $.ajax(  // ajax只接受一个参数选项对象
                    {
                        type: "GET",                   // HTTP请求方法
                        url:url,                      // 要获取数据的URL
                        data: null,                  // 不给url添加任何数据
                        dataType: "script",          // 一旦获取到数据,立刻当做脚本执行
                        success: function () {},    // 完成时调用该函数
                    }
                )

    jQuery.get()和jQuery.post()也接受上面的5个基本选项。然而,如果直接调用jQuery.ajax()的话,它可以支持更多其他选项。

    jQuery.ajaxSetup()传入一个选项对象来设置任意选项的默认值

                // 设置ajax默认参数
                $.ajaxSetup(
                    {
                        timeout: 2000,  // 在2秒后取消所有Ajax请求
                        cache: false    // 通过给URL添加时间戳来禁用浏览器缓存
                    }

    运行上面代码后,指定timeout和cache选项会在所有未指定这两个选项值的Ajax请求中使用(包括jQuery.get()和load()方法等高级工具)

    jQuery.ajax()选项

    type
        指定HTTP的请求方法。默认"GET"。另一个常用值是"POST"。可以指定其他HTTP请求方法
    比如"DELETE" 或 "PUSH",但不是所有的浏览器都支持它
    
    url
        要获取URL。对于GET请求,data选项会添加到该URL后。对于JSONP请求,当cache选项为false时
    jQuery可以添加参数到URL
    
    data
        添加到URL中(对GET请求)或在请求的内容体中(对于POST请求)发送的数据。这可以是字符串对象。
    通常会把对象转化为字符串
    
    dataType
        指定响应数据的期望类型,以及jQuery处理该数据的方式。合法值是"text"、"html"、"script""json"、"jsonp"和"xml"
    
    contentYpe
        指定请求的HTTP Content-Type头。默认是"application/x-www-form-urlencode",这是HTML表单和
    绝大部分服务器脚本使用的正常值。如果将type选项设置为"POST",想要发送纯文本或XML文档作为请求体时
    需要设置改选项
    
    timeout
        超时事件,单位是毫秒。如果设置了该选项,当请求没有在指定超时时间内完成时,请求会取消同时取消
    error回调,回调中的状态码为"timeout"。默认超时时间是0,表示除非请求完成,否则永远不会取消。
    
    cache
        对于GET请求,如果该选项设置为fales,jQuery会添加一个"_="参数到URL中,或者替换已经存在的同名参数
    改参数的值是当前时间(毫秒格式)。这可以禁用基于浏览器的缓存,因为每次请求的URL都不一样。
    
    ifModified
        当该选项设置为true时,jQuery会为请求的每一个URL记录Last-Modified和If-None-Match响应头的值
    并会在接下来的请求中为相同的URL设置这些头部信息。这可以使得,如果上次请求的URL内容没有改变,
    则服务器会发送HTTP 304 "Not Modified" 响应。默认情况下,该选项未设置,jQuery不会设置或记录这些信息
    
    global
        该选项指定jQuery是否应该触发上面描述的Ajax请求过程中的事件。默认值是true ,设置该选项为false会
    禁用Ajax相关的所有事件。

    jQuery.ajax()回调

    在Ajax请求的不同阶段调用的函数。success选项这是传入给jQuery.getJSON()等方法的回调函数,注意jQuery也会将Ajax请求过程消息当做事件发送(除非设置了global选项为false)

    context
        该选项指定回调函数在调用时的上下文对象---this。该选项没有默认值,如果不设置,this会
    指向选项对象。设置context选项也会影响Ajax事件触发的方式。如果设置该选项,值应该为
    Window、Document或触发事件所在的Element
    
    beforeSend
        该选项指定Ajax请求发送到服务器之前激活的回调函数,第一个参数是XMLHttpRequest对象,
    第二个参数是该请求对象的选项对象。beforeSend回调是的程序有机会在XMLHttpRequest对象上
    自定义HTTP头部。如果该回调函数返回false,Ajax请求会取消。
    
    success
        该选项定义Ajax请求陈工完成时调用的回调函数。第一个参数是服务器发送的数据;第二个
    参数是jQuery状态码;第三个参数是用来发送该请求的XMLHttpReques对象。
    
    error
        该选项指定Ajax请求不成功时调用的回调函数。参数与sucess类似
    
    complete
        该选项指定Ajax请求完成时激活的回调函数。每一个Ajax请求或者成功时调用success回调,
    或者失败时调用error。在调用success或error后,jQuery会调用complete回调。穿个complete
    回调的第一个参数是XMLHttpRequest对象,第二个参数则是状态码

    不常用的选项和钩子

    async
        脚本化的HTTP请求本身就是异步的。然后,XMLHttpRequest对象提供了一个选项,可以用来阻塞当前进程
    ,直到收到响应。如果想开启这一阻塞行为,可以设置该选项为false
    
    dataFilter
        该选项制定一个函数,用来过略或预处理服务器返回的数据。第一个参数是从服务器返回的原始数据
    (字符串或XML请求返回的Docuemnt对象),第二个参数是dataType选项的值,如果指定改函数,则它必返回
    一个值,改值会用来替换掉服务器的响应。注意dataFilter()函数会在JSON解析和脚本执行前执行,跨域的
    不会调用dataFilter()
    
    jsonp
        当设置dataType选项为"jsonp"时,url或data选项通常会包含一个类似"jsonp=?"的参数,如果没有找到
    类似的参数时,会使用默认值"callback"
    
    jsonpCallback
        对于dataType为"jsonp"的请求,jQuery必须将URL中的"?"替换成包装函数名,服务器会将数据传递给
    该包装函数。通常jQuery会根据当前事件生成一个唯一的函数名。如果想用自己的函数来替代jQuery生成的,
    则可以设置该选项。但是,一旦这样做了,会组织jQuery在触发正常事件调用success或complete回调
    
    processData
        当设置了data选项为对象时,jQuery通常会将 该对象转换成字符串
    
    scriptCharset
        对于跨域的"script"和"jsonp"请求,会使用<script>元素,该选项来指定<script>元素的charset属性值
    该选线个对于正常基于XMLHttpRequest请求的不会有任何作用
    
    username,password
        如果请求需要密码验证,请使用这两个选项来验证
    
    xhr
        该选项指定一个工厂函数,用来获取XMLHttpRequest对象。
  • 相关阅读:
    CF446C [DZY loves Fibonacci]
    [BZOJ2286] 消耗战
    [CF Round #278] Tourists
    BZOJ2553 [BJWC2011]禁忌
    NOI2018D2T1 屠龙勇士
    BZOJ2333 棘手的操作
    bzoj4196: [Noi2015]软件包管理器(树链剖分)
    bzoj1833: [ZJOI2010]count 数字计数(数位DP)
    bzoj1026: [SCOI2009]windy数(数位DP)
    bzoj3631: [JLOI2014]松鼠的新家(树上差分)
  • 原文地址:https://www.cnblogs.com/luotianshuai/p/7544408.html
Copyright © 2011-2022 走看看