浏览器

操作 DOM

始终记住 DOM 是一个树形结构。操作一个 DOM 节点实际上就是这么几个操作:

  • 更新:更新该 DOM 节点的内容,相当于更新了该 DOM 节点表示的 HTML 的内容;
  • 遍历:遍历该 DOM 节点下的子节点,以便进行进一步操作;
  • 添加:在该 DOM 节点下新增一个子节点,相当于动态增加了一个 HTML 节点;
  • 删除:将该节点从 HTML 中删除,相当于删掉了该 DOM 节点的内容以及它包含的所有子节点。
// 返回ID为'test'的节点:
var test = document.getElementById("test");

// 先定位ID为'test-table'的节点,再返回其内部所有tr节点:
var trs = document.getElementById("test-table").getElementsByTagName("tr");

// 先定位ID为'test-div'的节点,再返回其内部所有class包含red的节点:
var reds = document.getElementById("test-div").getElementsByClassName("red");

// 获取节点test下的所有直属子节点:
var cs = test.children;

// 获取节点test下第一个、最后一个子节点:
var first = test.firstElementChild;
var last = test.lastElementChild;

// 通过querySelector获取ID为q1的节点:
var q1 = document.querySelector("#q1");

// 通过querySelectorAll获取q1节点内的符合条件的所有节点:
var ps = q1.querySelectorAll("div.highlighted > p");

demo

<!-- html -->
<div id="test-div">
<div class="c-red">
<p id="test-p">JavaScript</p>
<p>Java</p>
</div>
<div class="c-red c-green">
<p>Python</p>
<p>Ruby</p>
<p>Swift</p>
</div>
<div class="c-green">
<p>Scheme</p>
<p>Haskell</p>
</div>
</div>
// 选择<p>JavaScript</p>:
var js = document.getElementById("test-p");

// 选择<p>Python</p>,<p>Ruby</p>,<p>Swift</p>:
var arr = document.getElementsByClassName("c-green")[0].children;

// 选择<p>Haskell</p>:
var haskell = document.getElementsByClassName("c-green")[1].lastElementChild;

更新

  • innerHTML
  • innerText // 会自动编码 不返回 hidden
  • innerContent // 自动编码

修改 css

// 获取<p id="p-id">...</p>
var p = document.getElementById("p-id");
// 设置CSS:
p.style.color = "#ff0000";
p.style.fontSize = "20px";
p.style.paddingTop = "2em";
<!-- HTML结构 -->
<div id="test-div">
<p id="test-js">javascript</p>
<p>Java</p>
</div>
// 获取<p>javascript</p>节点:
var js = document.getElementById("test-js");

// 修改文本为JavaScript:
// TODO:
js.innerHTML = "JavaScript";
// 修改CSS为: color: #ff0000, font-weight: bold
// TODO:
js.style.color = "#ff0000";
js.style.fontWeight = "bold";

插入

  • appendChild
  • insertBefore // 插到 ref 之前

appendChild

var
    list = document.getElementById('list'),
    haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.appendChild(haskell);

insertBefore

var
    list = document.getElementById('list'),
    ref = document.getElementById('python'),
    haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.insertBefore(haskell, ref);

删除

removeChild

// 拿到待删除节点:
var self = document.getElementById('to-be-removed');
// 拿到父节点:
var parent = self.parentElement;
// 删除:
var removed = parent.removeChild(self);
removed === self; // true

删除 web 不相关技术

<!-- HTML结构 -->
<ul id="test-list">
<li>JavaScript</li>
<li>Swift</li>
<li>HTML</li>
<li>ANSI C</li>
<li>CSS</li>
<li>DirectX</li>
</ul>
var parent = document.getElementById("test-list"),
web = ["JavaScript", "HTML", "CSS"];
for (var i of parent.children) {
if (web.indexOf(i.innerText) === -1) {
parent.removeChild(i);
}
}

操作表单

获取

// <input type="text" id="email">
var input = document.getElementById("email");
input.value; // '用户输入的值'
// <label><input type="radio" name="weekday" id="monday" value="1"> Monday</label>
// <label><input type="radio" name="weekday" id="tuesday" value="2"> Tuesday</label>
var mon = document.getElementById("monday");
var tue = document.getElementById("tuesday");
mon.value; // '1'
tue.value; // '2'
mon.checked; // true或者false
tue.checked; // true或者false

设置

// <input type="text" id="email">
var input = document.getElementById("email");
input.value = "test@example.com"; // 文本框的内容已更新

提交

  1. 绑定提交函数
<!-- HTML -->
<form id="test-form">
<input type="text" name="test">
<button type="button" onclick="doSubmitForm()">Submit</button>
</form>

<script>
function doSubmitForm() {
var form = document.getElementById('test-form');
// 可以在此修改form的input...
// 提交form:
form.submit();
}
</script>
  1. 响应 form onsubmin
<!-- HTML -->
<form id="test-form" onsubmit="return checkForm()">
<input type="text" name="test">
<button type="submit">Submit</button>
</form>

<script>
function checkForm() {
var form = document.getElementById('test-form');
// 可以在此修改form的input...
// 继续下一步:
return true;
}
</script>

hidden 使用

<!-- HTML -->
<form id="login-form" method="post" onsubmit="return checkForm()">
<input type="text" id="username" name="username">
<input type="password" id="input-password"> // 无name
<input type="hidden" id="md5-password" name="password">
<button type="submit">Submit</button>
</form>

<script>
function checkForm() {
var input_pwd = document.getElementById('input-password');
var md5_pwd = document.getElementById('md5-password');
// 把用户输入的明文变为MD5:
md5_pwd.value = toMD5(input_pwd.value);
// 继续下一步:
return true;
}
</script>

操作文件

var fileInput = document.getElementById("test-image-file"),
info = document.getElementById("test-file-info"),
preview = document.getElementById("test-image-preview");
// 监听change事件:
fileInput.addEventListener("change", function () {
// 清除背景图片:
preview.style.backgroundImage = "";
// 检查文件是否选择:
if (!fileInput.value) {
info.innerHTML = "没有选择文件";
return;
}
// 获取File引用:
var file = fileInput.files[0];
// 获取File信息:
info.innerHTML =
"文件: " +
file.name +
"<br>" +
"大小: " +
file.size +
"<br>" +
"修改: " +
file.lastModified;
if (
file.type !== "image/jpeg" &&
file.type !== "image/png" &&
file.type !== "image/gif"
) {
alert("不是有效的图片文件!");
return;
}
// 读取文件:
var reader = new FileReader();
reader.onload = function (e) {
// 回调
var data = e.target.result; // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...'
preview.style.backgroundImage = "url(" + data + ")";
};
// 以DataURL的形式读取文件 base64格式:
reader.readAsDataURL(file); // 异步读取
});

AJAX

function success(text) {
var textarea = document.getElementById("test-response-text");
textarea.value = text;
}

function fail(code) {
var textarea = document.getElementById("test-response-text");
textarea.value = "Error code: " + code;
}

var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象

request.onreadystatechange = function () {
// 状态发生变化时,函数被回调
if (request.readyState === 4) {
// 成功完成
// 判断响应结果:
if (request.status === 200) {
// 成功,通过responseText拿到响应的文本:
return success(request.responseText);
} else {
// 失败,根据响应码判断失败原因:
return fail(request.status);
}
} else {
// HTTP请求还在继续...
}
};

// 发送请求:
request.open("GET", "/api/categories");
request.send(); // 真正发送

alert("请求已发送,请等待响应...");

XMLHttpRequest 对象的 open()方法有 3 个参数,第一个参数指定是 GET 还是 POST,第二个参数指定 URL 地址,第三个参数指定是否使用异步,默认是 true,所以不用写。

CORS

CORS 全称 Cross-Origin Resource Sharing,是 HTML5 规范定义的如何跨域访问资源。

假设本域是 my.com,外域是 sina.com,只要响应头 Access-Control-Allow-Origin 为http://my.com,或者是*,本次请求就可以成功。

可见,跨域能否成功,取决于对方服务器是否愿意给你设置一个正确的 Access-Control-Allow-Origin,决定权始终在对方手中。

上面这种跨域请求,称之为“简单请求”。简单请求包括 GET、HEAD 和 POST(POST 的 Content-Type 类型 仅限 application/x-www-form-urlencoded、multipart/form-data 和 text/plain),并且不能出现任何自定义头(例如,X-Custom: 12345),通常能满足 90%的需求。

Promise

Canvas

jQuery

选择器

操作 dom

事件

动画

AJAX

扩展

错误处理

underscore

node.js