WEB前端开发之原生DOM&jQuery-DOM编程
美丽说商业前端负责人 赵先烈
新浪微博:@阿烈先生
微信:www-baidufe-com
个人网站:http://www.baidufe.com
开课时间:2014-07-04(08:50-11:25)
开课地点:清华大学 五教201教室

课程大纲

课程大纲

第一章:DOM基础

一、认识DOM

1、DOM是什么?

Document Object Model,文档对象模型,可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构,是表示和处理一个HTML或XML文档的常用方法。

2、DOM能做什么?

能让网页实现更丰富的交互效果,下面随便列几个网站看欣赏一下DOM的奇幻魅力!

  1. 新浪微博Feed数据的下拉无限加载:http://www.weibo.com/
  2. Fehelper首页上的图片幻灯切换功能:http://www.baidufe.com/fehelper
  3. 无尽的隧道:http://js1k.com/2013-spring/demo/1555

二、DOM节点

一个完整的网页,就是由不同类型的HTML DOM节点,按照一定的依赖规则组合而成的。

1、DOM中对节点的定义

2、节点类型

DOM节点类型

实例分析

3、节点层次

1)、HTML文档

        <!DOCTYPE HTML>
        <html lang="en-US">
            <head>
                <meta charset="UTF-8">
                <title>文档标题</title>
            </head>
            <body>
                <h1>我的标题</h1>
                <a href="http://www.baidu.com">我的链接</a>
            </body>
        </html>
    

2)、DOM树

如上HTML文档所示的DOM节点层次,可以通过一棵HTML DOM树体现出来

HTML DOM树

要理解DOM树在浏览器中的渲染顺序:从根节点自上而下进行渲染

BTW:通过之后章节中即将介绍的DOM操作,可以访问整个DOM树上的所有节点,包括节点的查改增删。

三、DOM节点的查改增删

本节将主要学习HTML DOM节点的查找、修改、创建与插入、删除等操作。

1、节点查询

1)、查询DOM节点

简要介绍getElementById、getElementsByTagName、getElementsByClassName,示例代码:

        // 查询id为 helloWorld 的节点
        var helloWorld = document.getElementById('helloWorld');

        // 查询页面上的所有 a 标签
        var aTags = document.getElementsByTagName('a');

        // 查询class为 .slide 的节点
        var slides = document.getElementsByClassName('slide');
    

感兴趣的可以再试试:querySelector、querySelectorAll

实例分析

2)、访问父节点与子节点

简要介绍parentNode、childNodes、firstChild、lastChild,示例代码:

        // 查询id为 helloWorld 的节点
        var helloWorld = document.getElementById('helloWorld');

        // 获得helloWorld的父节点
        // 这里使用的是parentNode,在非w3c标准下还有一个parentElement,必须理解二者的区别:
        // ElementNode只是Node中的一种,nodeType为1
        var parentNodeForHelloWorld = helloWorld.parentNode;

        // 获得helloWorld的所有子节点
        var childNodesForHelloWorld = helloWorld.childNodes;

        // 获取hellWorld的第一个子节点
        var firstChildForHelloWorld = helloWorld.firstChild;

        // 获取hellWorld的最后一个子节点
        var lastChildForHelloWorld = helloWorld.lastChild;
    

BTW:必须理解firstChild和lastChild都是获取所有类型的Node,而不仅仅是ElementNode。

实例分析

3)、访问兄弟节点

简要介绍previousSibling、nextSibling,示例代码

        // 查询id为 helloWorld 的节点
        var helloWorld = document.getElementById('helloWorld');

        // 获得helloWorld的前一个兄弟节点
        var previousNodeForHelloWorld = helloWorld.previousSibling;

        // 获得helloWorld的后一个兄弟子节点
        var nextNodeForHelloWorld = helloWorld.nextSibling;
    

BTW:必须理解previousSibling和nextSibling都是获取所有类型的Node,而不仅仅是ElementNode。
如果只想获取ElementNode,可以使用previousElementSibling和nextElementSilbling方法, 但这两个属性不是w3c标准,存在浏览器兼容性问题,慎用。

实例分析

2、节点修改

1)、修改节点属性

节点属性的修改,可以通过element.setAttribute、element.attributeName的方式进行修改,比如针对如下节点:

        <a id="helloWorld" class="cls-demo red" href="http://www.baidufe.com">http://www.baidufe.com</a>
    

可通过下面的两种方式,直接修改该节点的链接地址:href属性

        // 查询id为 helloWorld 的A节点
        var helloWorld = document.getElementById('helloWorld');

        // 修改helloWorld的href值:通过element.setAttribute的形式
        helloWorld.setAttribute('href','http://www.baidu.com');

        // 修改helloWorld的href值:通过element.attributeName的形式
        helloWorld.href = 'http://www.baidu.com';
    

实例分析

但是,不是所有的属性都可以直接通过element.attributeName赋值的形式来实现,比如,节点的CSS class就是一个特例:

        // 我们可以通过element.setAttribute的形式来修改class
        helloWorld.setAttribute('class','cls-demo-changed'); // success

        // 但我们不能通过element.attributeName的形式来修改class
        helloWorld.class = 'cls-demo-changed'; // failed

        // 对于CSS class,正确的做法是:
        helloWorld.className = 'cls-demo-changed'; // success
    

BTW:关于节点CSS class的访问,在HTML5标准中新增了classList API,该API中新增了CSS class的add、remove、contains、item、toggle等方法

        // 通过classList的contains方法,判断节点是否包含某个CSS class
        var hasClass = helloWorld.classList.contains('red'); // true

        // 其他API可线下单独尝试
    

2)、修改节点内容

本小节主要介绍节点内容的修改方法,包括修改HTML片段,以及文本内容;主要API为:innerHTML、innerText

        // 继续以上一小节的<a>节点作为示例
        var helloWorld = document.getElementById('helloWorld');

        // 修改链接文本为:清华大学
        helloWorld.innerHTML = '清华大学';
        // 或通过innerText属性修改
        helloWorld.innerText = '清华大学';

        // 将链接文本替换成一张图片,即插入一个<img/>标签,此时只能使用innerHTML属性
        helloWorld.innerHTML = '<img src="static/img/picture.png?v=78964693&v=59764449" alt="图片" />';
    

实例分析

3、增加新节点

本节将介绍如何通过DOM动态创建新节点,并插入到文档中,用到的API:createElement、appendChild,假定文档如下:

        <div id="helloWorld">
            <div id="inner"></div>
        </div>

此时则可以通过如下的DOM操作,动态创建一个img节点并插入到helloWorld中

        // 获得helloWorld节点
        var helloWorld = docuement.getElementById('helloWorld');

        // 通过createElement创建img节点,并设置相关属性
        var imgElement = document.createElement('img'); // 注意API的使用方法
        imgElement.src = '/static/img/picture.png?v=78964693&v=59764449'; // 设置图片地址
        imgElement.alt = '图片';

        // 将img追加到helloWorld子节点之后
        helloWorld.appendChild(imgElement); // 采用子节点追加的方式插入文档
    

BTW:当有大批量的DOM节点需要插入到文档流中,需要用DocumentFragment来实现

实例分析

通过上面的DOM操作,文档片段将发生如下的变化:

        <div id="helloWorld">
            <div id="inner"></div>
            <img src="/static/img/picture.png?v=78964693&v=59764449" alt="图片" />
        </div>
    

列举一个简易的DocumentFragment示例:

        // 创建一个文档碎片
        var docFrag = document.createDocumentFragment();
        // 在碎片上加入100个div节点
        for(var i = 0;i < 100;i++){
            docFrag.appendChild(document.createElement('div'));
        }
        // 加docFrag加入到DOM-Tree
        document.body.appendChild(docFrag);
    

BTW:在项目开发中,用得最多的还是createElement、appendChild,其他API一般都会进行封装后再使用,可留作课后作业自行练习。

4、删除节点

本节将简单介绍从文档中将DOM节点进行删除操作,主要通过父节点的removeChild方法来实现。已如下HTML文档为例:

        <div id="container">
            <div id="helloWorld"></div>
        </div>

现在通过下面的DOM操作,来实现hellWorld节点的删除操作

        // 获得待删除的节点
        var helloWorld = document.getElementById('helloWorld');

        // 调用父节点的removeChild方法来实现自身节点的删除
        helloWorld.parentNode.removeChild(helloWorld); // 注意参数
    

如上代码执行成功后,文档将会发生如下变化:

        <div id="container"></div>
    

注:目前部分高大上一点的浏览器(如Chrome)已经支持element.remove()直接移除节点本身:

        document.getElementById('helloWorld').remove();
    

实例分析

四、DOM相关的几个重要对象

关于DOM操作,浏览器提供了较多内置对象,具体可以从下面文档中得到参考:

但是本节只简单介绍几个比较典型的对象。

1、window对象

包括了整个WEB页面中所有可执行的Javascript API;另外,可详细了解alert()、confirm()、prompt()、close()、onload()

2、document对象

DOM编程中,最常用的对象,可详细了解cookie、title、URL、write()、getElementById()

3、navigator对象

通过此对象可以获取操作系统信息、浏览器信息等,在HTML5中,还可以获取地理位置、联网状态等; 可详细了解platform、userAgent、geolocation、onLine

4、location对象

包含当前页面URL相关的信息,并能控制页面的跳转等操作,可详细了解href、hash、search、protocal、reload()、replace(); 另外,location.href值等同于document.URL

五、实例分析

  1. 新浪微博Feed数据的下拉无限加载:http://www.weibo.com/
  2. Fehelper首页上的图片幻灯切换功能:http://www.baidufe.com/fehelper
  3. 无尽的隧道:http://js1k.com/2013-spring/demo/1555

用截止目前讲到的DOM操作,分析一下上面实例的实现原理。

第二章:DOM事件模型

一、事件的分类

1、鼠标事件

click、dbclick、mousedown、mouseup、mouseover、mousemove、mouseout等

2、键盘事件

kyedown、keyup、keypress等

3、表单事件

select、change、submit、focus、blur等

4、媒介事件

play、playing、abort、cancel等

5、HTML5事件

online、offline、message、popstate等

6、页面事件

load、error、resize、scroll等

7、WebApp事件

orientationchange、touchstart、touchmove、touchend等

二、添加事件处理程序

给DOM节点增加事件处理程序也有多种方法,本节都将进行简单介绍

1、通过节点属性显式声明

如下示例代码,表示直接在HTML中,显式地为按钮绑定了click事件,当该按钮有用户点击行为时,便会触发myClickFunc方法

        <button id="btnHello" onclick="myClickFunc()">ClickMe</button>
    

myClickFunc的定义则在js中完成,示例如下:

        // 事件处理程序的定义
        var myClickFunc = function(evt){
            // TODO ...
        };
    

实例分析

2、通过节点属性动态绑定

这种事件处理程序的绑定,属于第一种的变种形式

        <button id="btnHello">ClickMe</button>
    

通过DOM操作进行动态绑定:

        // 事件处理程序的定义
        var myClickFunc = function(evt){
            // TODO ...
        };

        // 直接给DOM节点的 onclick 方法赋值,注意这里接收的是一个function
        document.getElementById('btnHello').onclick = myClickFunc;
    

实例分析

3、通过事件监听的方式

相比而言,是事件处理程序的升级模式,是最靠谱的绑定方式,并且能给DOM节点增加多个事件监听,但不能绑定多个onclick事件

        <button id="btnHello">ClickMe</button>
    

通过DOM操作进行动态绑定:

        // 获取btnHello节点
        var btnHello = document.getElementById('btnHello');

        // 增加第一个 click 事件监听处理程序
        btnHello.addEventListener('click',function(evt){
            // TODO sth 1...
        },false);

        // 增加第二个 click 事件监听处理程序
        btnHello.addEventListener('click',function(evt){
            // TODO sth 2...
        },false);

BTW:通过此中形式,可以给btnHello按钮绑定任意多个click监听; 注意,执行顺序与添加顺序相关

实例分析

三、移除事件处理程序

移除的方法必须和添加的方法相对应

实例分析

四、深入Event对象

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。 事件通常与函数结合使用,函数不会在事件发生前被执行!

1、Event对象的一些重要属性和方法

2、事件冒泡(传播)

事件触发时,会从目标DOM元素向上传播,直到文档根节点,一般情况下,会是如下形式传播:

targetDOM → parentNode → ... → body → document → window

如果希望一次事件触发能在整个DOM树上都得到响应,那么就需要用到事件冒泡的机制,如下示例代码:

        <button id="btnHello">ClickMe</button>
    
        // 给按钮增加click监听
        document.getElementById('btnHello').addEventListener('click',function(evt){
            alert('button clicked');
        },false);

        // 给body增加click监听
        document.body.addEventListener('click',function(evt){
            alert('body clicked');
        },false);
    

在这种情况下,点击按钮“ClickMe”后,其自身的click事件会被触发,同时,该事件将会继续向上传播, 所有的祖先节点都将得到事件的触发命令,并立即触发自己的click事件;所以如上代码,将会连续弹出两个alert

实例分析

有些情况下,我们的需求要求,每个事件都是独立触发,所以我们必须阻止事件冒泡,针对如上示例代码,可改造为:
    // 给按钮增加click监听
    document.getElementById('btnHello').addEventListener('click',function(evt){
        alert('button clicked');
        evt.stopPropagation(); // 这条命令就能将此次事件完全结束掉,阻止冒泡
    },false);

    // 给body增加click监听
    document.body.addEventListener('click',function(evt){
        alert('body clicked');
    },false);
    

此时,点击按钮后,只会触发按钮本身的click事件,得到一个alert效果;该按钮的点击事件,不会向上传播,body节点就接收不到此次事件命令。

有两点需要注意:

实例分析

3、事件默认行为

在项目过程中,我们会遇到各种各样的需求,比如:

其实,这些需求都可以通过阻止事件的默认行为来完成,具体可以看下面的这个示例:

        <a id="aBaiduFe" href="http://www.baidufe.com">BaiduFe</a>
    

要求:点击BaiduFe链接后,页面不能发生跳转,而是弹出一个alert

        // 给a标签增加click事件监听
        document.getElementById('aBaiduFe').addEventListener('click',function(evt){
            alert('对不起,页面不会发生跳转!');
            evt.preventDefault(); // 阻止默认行为
        },false);

BTW:其他情况均可通过这样的方式进行事件默认行为的阻止,至于阻止的方法,在不同浏览器中会存在差异,后续章节将会介绍兼容性的处理办法

实例分析

五、实例分析

  1. Flying Fireworm:http://js1k.com/2014-dragons/demo/1723
  2. Flappy Dragon:http://js1k.com/2014-dragons/demo/1659
  3. 2048:http://js1k.com/2014-dragons/demo/1824

用截止目前学到的DOM操作 & 事件模型 知识,分析如上实例的实现原理

第三章:基于jQuery的DOM编程

一、万能的$

$符是jQuery的一个别名,通过它,能完成非常丰富的DOM操作,比如拿百度首页来做个小测试:

给百度首页所有的A链接都增加一个点击事件,点击后弹框显示链接内容;
并且将搜索框上方的前两个A链接颜色改为红色,第三个之后的A链接背景色改为随机。

        // 给所有的A标签都增加点击事件
        $('a').click(function(e){
            alert($(this).attr('href'));
        });

        // 生成随机颜色值:#RRGGBB
        var getRandomColor = function(){
            return '#' + (new Number(Math.floor(Math.random() * 256))).toString(16)
                + (new Number(Math.floor(Math.random() * 256))).toString(16)
                + (new Number(Math.floor(Math.random() * 256))).toString(16);
        };
        // 将搜索框上方的A标签改成不同颜色
        $('#nv a')                                          // 查询到搜索框上方的所有A链接
            .filter(':lt(2)').css('color','#f00')           // 将前两个A标签颜色改成红色
            .end()
            .filter(':gt(2)').each(function(){             // 将第三个标签之后的全部标签背景色改为随机
                $(this).css('background',getRandomColor());
            });
    

写更少的代码,做更多的事情!

二、jQuery选择器

基本

子元素筛选

内容筛选

基本筛选

层级

属性

可见性筛选

表单

运用选择器--jQuery DOM查找

        // 把id为nv、标签名为span、以及class名为reg的a标签都查出来
        $('#nv, span, a.reg');

        // 把页面上第 5 个a标签查出来
        $('a:eq(5)');

        // 把页面上第 5N 个a标签都查出来
        $('a:nth-child(5n)');

        // 把页面上所有隐藏起来的标签都查出来
        $('*:hidden');

        // 把 body 标签下所有隐藏起来的标签,但标签名不是a和script的标签都查出来
        $('body :hidden:not(a,script)');

        // 把 内容包含“贴” 的a标签都查出来
        $('a:contains("贴")');

        // 把 同时带有id属性、class属性的标签都查出来
        $('[id][class]');

        // 把 带有id属性,且class属性以“s_”开头的标签都查出来
        $('[id][class^=s_]');

        // 把 所有的复选框都查出来
        $('input:checkbox');

        // 把所有处于选中状态的单选框都查出来
        $('input:radio:checked');
    

jQuery DOM与原生DOM之间的转换

首先简单分析下jQuery源代码,搞清楚$查找出来的结果是什么样的: $( selector, context )

            jQuery.fn.init = function(selector,context){
                    // HANDLE: $(#id)
                    } else {
                        elem = document.getElementById( match[2] );
                        if ( elem && elem.parentNode ) {
                            // Inject the element directly into the jQuery object
                            this.length = 1;
                            this[0] = elem;
                        }
                        this.context = document;
                        this.selector = selector;
                        return this;
                    }
                    // HANDLE: $(expr, $(...))
                    } else if ( !context || context.jquery ) {
                        return ( context || rootjQuery ).find( selector );
                    // HANDLE: $(expr, context)
                    } else {
                        return this.constructor( context ).find( selector );
                    }
                // HANDLE: $(DOMElement)
                } else if ( selector.nodeType ) {
                    this.context = this[0] = selector;
                    this.length = 1;
                    return this;
            }
        
能很清楚的看出来,每个DOM元素是被封装到一个数组中的。

从前面的代码不难总结出,jQuery DOM元素和原生DOM元素之间存在这样的关系:

        // 获取 id=helloWorld 节点的jQuery对象
        var jqDom = $('#helloWorld');
        // 从jQuery对象中提取原生DOM
        var el = jqDom[0];
        // 或者通过jQuery对象提供的get(index)方法
        var el = jqDom.get(0);

        // 多个结果集的情况也一样
        var jqDoms = $('#a,#b,#c');
        // 获取 #b 对应的原生DOM
        var elB = jqDoms.get(1);
    

而原生DOM对象到jQuery对象的转换,已经在$中实现:

        // 获取 id=helloWorld 节点的原生对象
        var el = document.getElementById('helloWorld');
        // 转 jQuery 对象,直接用 $ 包装一下即可(参考前面jQuery.fn.init方法中的实现)
        var jqDom = $(el);
    

另外,必须知道jQuery提供的each等遍历方法,获取到的item都是原生DOM

        // 获取所有 class=x-hello 的标签,并遍历进行单独处理
        $('.x-hello').each(function(index,item){
            // 这里的 item 是DOM原生对象,也可以用 this 获取
            // 将每个 item 作为jQuery对象来使用
            $(item);    // or $(this);
        });
    

三、DOM节点的增加与移除

1、首先看如何创建jQuery DOM节点

通过 $(htmlContent) 的方式创建jQuery节点

        // 创建一个 div 节点
        $('<div/>');

        // 创建一个 id=helloWorld,class=x-hello 的div节点
        $('<div id="helloWorld" class="x-hello"/>');

        // 或者用原生DOM的方式先创建,再包装成jQuery DOM(如果有这个需要的话)
        var div = document.createElement('div');
        div.id = 'helloWorld';
        div.className = 'x-hello';
        var jqDiv = $(div);
    

2、用append、appendTo或prepend、prependTo将DOM添加到页面

        // 创建一个 id=helloWorld,class=x-hello 的div节点
        var jqDiv = $('<div id="helloWorld" class="x-hello"/>');

        // 通过 append 添加到页面
        $('body').append(jqDiv);

        // 通过appendTo添加到页面
        jqDiv.appendTo('body');
    

其他添加DOM节点的API这里就不列举了,课后可单独练习

3、DOM节点移除

        // 将 id=helloWorld、class=x-hello、以及所有strong标签都删掉
        $('#helloWorld, .x-hello, strong').remove();

        // 将 div#container 下的所有子节点都删掉
        $('#container').empty();
    

可结合前面章节讲到的原生DOM操作,思考jQuery中这些API的实现原理。
其他添加DOM节点的API这里就不列举了,课后可单独练习。

四、属性与CSS操作

简单示例

jQuery中大部分DOM属性操作与CSS操作的方法,都是getter和setter合一的,如:

        // setter:设置 id=helloWorld 节点的 data-hello 属性
        $('#helloWorld').attr('data-hello','Hello,I am Alien!');

        // getter:获取 id=helloWorld 节点的 data-hello 属性
        var attr = $('#helloWorld').attr('data-hello');
    
一些CSS相关的操作:
        // 给 id=helloWorld 节点增加一个 x-hello 的class
        $('#helloWorld').addClass('x-hello');
        // 增加多个class,用逗号隔开
        $('#helloWorld').addClass('cls1 cls2 cls3');

        // 移除 x-hello class
        $('#helloWorld').removeClass('x-hello');
    
节点宽高相关:
        // 获取 id=helloWorld 的宽
        var width = $('#hellWorld');

        // 设置 宽=200px,高=300px
        $('#hellWorld').width(200).height(300);
    

其他API可课后进行练习

五、jQuery事件处理

浏览器事件

文档加载

事件绑定

表单事件

键盘事件

鼠标事件

事件对象

1、页面加载完成后执行:ready

        // 写法1:
        $(document).ready(function(){
            // TODO ...
        });

        // 写法2:
        $(function(){
            // TODO ...
        });
    

这个方法的作用是告诉浏览器,在文档加载完成后再执行 TODO 的代码;
如果文档未加载完成, 就不要执行,因为可能会有异常情况,比如某些DOM获取不到等等。


2、添加事件监听

        // 给 id=helloWorld 的节点增加mousedown、mouseup事件
        $('#helloWorld').mousedown(function(e){
            // TODO ...
        }).mouseup(function(e){
            // TODo ...
        });
    

3、也可以通过bind方式绑定事件,包括自定义事件

        // 给 id=helloWorld 的节点增加mousedown、mouseup事件,以及自定义事件:sayHello
        $('#helloWorld').bind({
            mousedown : function(e){
                // TODO ...
            },
            mouseup : function(e){
                // TODO ...
            },
            sayHello : function(e){ // 自定义事件
                // TODO ...
            }
        });
    


4、通过trigger强制触发事件(包括自定义时间)

        // 触发 id=hellWorld 节点的 mouseup, sayHello 事件
        $('#helloWorld').trigger('mouseup').trigger('sayHello');
    

5、在事件绑定时传递参数

有时候有种特殊需求,在事件处理的handler中需要用到外界的数据,于是可以这样做:

        var message = 'Hi,I am Alien!';
        $('#helloWorld').click({msg : message},function(e){
            // 通过 e.data 的方式来获取handler绑定时传入的参数
            alert(e.data.msg);
        });
    

可能还有更变态的需求,希望在事件触发时动态传入参数,比如自定义事件:

        // 当 sayHello 事件触发的时候,显示 message
        $('#helloWorld').bind('sayHello',function(e, name, message) {
            // 动态的输出 message
            alert(name + ',' + message);
        });

        // 强制触发 sayHello 的时候,动态指定 message
        // 注意,trigger的第二个参数是一个 Array,代表 eventHandler第一个参数之后的所有参数
        $('#hellWorld').trigger('sayHello', [ 'John', 'Hi,I am Alien!' ] );
    

感兴趣的同学,课后可练习一下

6、在jQuery事件中处理冒泡和默认行为

jQuery已经处理完了所有浏览器的兼容性,所以直接用标准的方法来操作就行

        // id=helloWorld 的节点点击后,阻止事件冒泡
        $('#helloWorld').click(function(e){
            // TODO ...

            // 阻止冒泡
            e.stopPropagation();
        });

        // 表单 form#info 提交时,如果数据不合法则取消提交
        $('form#info').submit(function(e){
            // 验证表单
            var isValid = validateTheForm(this);

            // 如果不合法,则取消提交
            if(!isValid){
                e.preventDefault();
            }
        });
    

当然,如果你的需求是阻止事件冒泡,并且取消事件的默认行为,则可以直接 return false

        // 用 a 标签做了个按钮,点击时需要阻止事件冒泡,同时取消默认的跳转行为
        $('a.btn').click(function(e){
            // TODO ...

            return false;
        });
    

六、jQuery动画

第四章:利用Chrome DevTool进行DOM调试

本节将重点现场演练Chrome DevTool的使用方法

chrome开发者工具

Chrome devTool相关导读:

  1. console api
  2. command line api
  3. 使用Chrome DevTools的Timeline和Profiles提高Web应用程序的性能

随堂综合练习

如下是2013年Google I/O大会上关于实时WEB应用的一个简短视频,在多个端(pad、phone、pc)上同时打开网页, 并拼接一个环形赛车跑道,玩家可以在这个跑道上进行赛车游戏。请看完视频后, 结合本次DOM编程的相关知识,分析该功能的实现原理

Q/A

/

#