Front end foundation course 9

上节课的作业

function parseTemplate(template, data) {
    for (var key in data) {
        template = template.replace('{{' + key + '}}', data[key], 'gi');
    }
    return template;
}

这里简单说一下 cookie,当然我们要说的不是这个好吃的曲奇饼,而是一种储存数据的方式。

Cookie 是一种本地浏览器储存技术,即开发者可以通过一些技术手段将一些信息存放在用户浏览器端。 它的官方规范定义在 RFC6265,主要用于在用户本地浏览器记录一些用户个人信息,如身份辨识、一些状态选择等。

常见的设置 cookie 的方式有两种:

  • 通过在请求的 response 的 header 中加入一些相关字段来设置
  • 通过 JS 代码来设置

对于第一种方式,这里只是举个例子,不做过多的介绍,感兴趣的同学可以自行搜索相关资料。

对于第二种方式,我们在下面讲 document 的时候会提到,这里先暂时跳过。

DOM 基础 Part 1

什么是 DOM

DOM 即 Document Object Model,文档对象模型。大体上可以分为核心 DOM、XML DOM 和 HTML DOM。 它由 W3C 组织制定相关规范,规范中定义了针对 HTML、XML 的文档中的各种不同对象,以及这些对象的属性、方法、事件等内容。

DOM、JS 和 浏览器

浏览器作为一个环境按照 DOM 规范实现了相关的功能,从而把 HTML 文档解析成相应的 DOM 结构。 并且通过实现 DOM 规范中定义的各种接口,将它们暴露给 JS,从而让 JS 能够方便的进行各种 DOM 操作。 详情可见官方文档

JS 通过 DOM 能做什么

  • 能够改变页面中的所有 HTML 元素
  • 能够改变页面中的所有 HTML 属性
  • 能够改变页面中的所有 CSS 样式
  • 能够对页面中的所有事件做出反应
  • e.t.c

DOM 树

HTML 文档在浏览器中会被解析为 DOM 树,其中每个节点即 DOM 节点,我们用 JS 可以对这些 DOM 节点做出各种规范中定义的操作。

对于如下的 HTML 结构:

<html>
    <head>
        <title>My title</title>
    </head>
    <body>
        <a href="">My link</a>
        <h1>My header</h1>
    </body>
</html>

它解析后的 DOM 树为:

DOM树

其中节点的关系为:

DOM节点

document

document 即文档,在浏览器中 document 对象是一个 HTML 文档解析成 DOM 后的根节点。 document 节点继承了 NodeEventTarget,它包含了网页的内容和 DOM 树,并且提供了很多特有的方法。

document.head

document.head 是个只读属性,返回当前文档的第一个 <head> 元素。

document.body

document.body 是个只读属性,返回当前文档的 <body> 元素。

document.title

document.title 属性用于获取或者设置当前文档的标题。

var curTitle = document.title;
document.title = 'new title';

document.cookie

document.cookie 属性用于获取或者设置当前文档的 cookie

var curCookie = document.cookie;
document.cookie = 'new cookie';

cookie 在设置的时候内容格式为键值对的形式,中间用 = 号建立联系,不同的项之间用 ; 分隔。 除了主要的内容键值对以外,常见的设置项有 domain, path, expires,具体的意思有兴趣的同学可以去自行搜索。

这些对于 cookie 的操作,

function set(key, value, config) {
    var DAY = 24 * 60 * 60 * 1000,
        now = new Date();

    config = $.extend({
        expire: 30,
        path: '/',
        domain: window.location.hostname
    });

    now.setTime(now.getTime() + config.expire * DAY);
    document.cookie = key + "=" + encodeURIComponent(value) + "; domain=" + config.domain + "; path=" + config.path + "; expires=" + now.toGMTString();
}

function get(key) {
    var keys = document.cookie.split("; "),
        len = keys.length, tmp;

    while (len--) {
        tmp = keys[len].split('=');
        if (tmp[0] === key) {
            return decodeURIComponent(tmp[1]);
        }
    }
}

function unset(key) {
    set(key, false, -1);
}

节点访问

getElementById

element = document.getElementById(id);

该方法通过 id 属性来获取对应的节点。由于 id 属性的唯一性,所以返回的结果通常为空或一个唯一的节点。

getElementsByTagName

elements = element.getElementsByTagName(tagName);

该方法通过标签名称来获取属于该类标签的节点的动态集合。 其中动态即指通过其他方式更改了节点相应的内容时,节点集合的内容也会产生变化。 具体的我们看个例子。

getElementsByClassName

elements = element.getElementsByClassName(names);

该方法通过类名来获取包含该类的节点的动态集合。 其中类名只要包含即可,具体我们看个例子。

querySelector

querySelectorquerySelectorAll 可以使用 css 选择器的方式来选择对应的节点。相对于上述方法而言,使用起来方便很多,不过IE 8+ 才支持。 如:

document.querySelector(".myclass");
document.querySelector("style[type='text/css'], style:not([type])");

节点操作

获取节点

除了 getElementsByTagNamegetElementsByClassName 以外,我们还有一些特定亲属节点的获取方法。

  • firstChild
  • firstElementChild
  • lastChild
  • lastElementChild
  • nextSibling
  • nextElementSibling
  • parentNode
  • parentElement

修改内容

innerHTML

通过 innerHTML 属性可以非常方便的获取和设置节点内部的 html 内容。如:

<body>
    <h1>Title</h1>
    <script>
        console.log(document.body.innerHTML);
        document.body.innerHTML = '<p>Hello world</p>';
    </script>
<body>

需要注意的是,设置进去的字符串会被按照 html 来解析,例如一些特殊编码 &#9824;,又或者是一些正常的标签 <img src="">。 所以,如果对用户输入的字符串直接进行这个操作,其实是非常危险的。例如大家可以尝试一下这个操作:

document.body.innerHTML = '<script>alert(document.cookie)</script>';
textContent

通过 textContent 属性可以非常方便的获取和设置节点内部的文本内容。如:

<body>
    <h1>Title</h1>
    <script>
        var ele = document.querySelector('h1');
        console.log(ele.textContent);
        ele.textContent = 'Hello World';
    </script>
<body>

修改节点属性

通过 getAttributesetAttribute 或者直接对属性进行操作可以非常方便的获取和设置节点的属性。 如:

<img id="image" src="http://www.baidu.com/img/bdlogo.png">

<script>
document.getElementById("image").src="https://www.google.com/images/srpr/logo11w.png";
document.getElementById("image").setAttribute('class', 'pic');
</script>

修改节点样式

通过修改 style 对象上的各种属性,可以非常方便的修改与之对应的 dom 属性。 具体的属性列表可以看这篇文档。 如:

<p id="p1">我是段落,要变色</p>
<script>
    document.getElementById('p1').style.color="red";
</script>

创建新节点

通过 createElement 方法可以非常方便的创建新的 dom 节点,其参数为创建的节点的标签名。 需要注意的是,创建的节点并不是在页面上,而是在内存中。如需显示,则需要添加到页面上。 如:

var para=document.createElement("p");
para.innerHtml="我是新添加的段落";
console.log(para);

添加节点

通过 appendChildinsertBefore 方法可以非常方便的向页面中添加节点。 如:

<div id="list">Content</div>
<script>
    var list = document.getElementById('list'),
        p = document.createElement('p'),
        p2 = document.createElement('p');
    p.innerHTML = 'appendChild';
    p2.innnerHTML = 'insertBefore';
    list.appendChild(p);
    list.insertBefore(p2, p);
</script>

删除节点

通过 removeChild 方法可以非常方便的删除页面中的节点。 如紧接着上例:

list.removeChild(p);
list.removeChild(p2);

替换节点

通过 replaceChild 方法可以非常方便的替换页面中的节点。第一个参数为新节点,第二个参数为替换的目标节点。 如:

var btn1 = document.getElementById("btn1");
var btn3 = document.createElement("button");
btn3.id = "btn3";
btn3.innerText = "新按钮";
c1.replaceChild(btn3, btn1);

DEMO

现在教学方式更偏向实战化,所以打算在课程中加入一些 demo 的部分,希望巩固已有的理论知识。

本次的 demo 是为了复习和巩固 HTML 和 CSS 的基础知识,所以我们来一起仿造一个静态页面。

Homework

  1. 练习课上学到的 DOM 节点的获取和相关操作。
  2. 静态页面个人自由训练。
  3. 做一个时钟页面,现实动态当前时间。
  4. 数据为对象结构的省份和城市信息,请用 JS 和 HTML 构造相应的选择项。

预告

下节课主要内容为 DOM 事件。

Fighting!

2015.01.04