DOM

你的 HTML 文件加载一次,然后页面就坐在那里。但是一个随着你输入而建议结果的搜索框、一个点击时打开的菜单、一个滴答计数的计数器,这些都不在 HTML 文件中。加载后有东西改变了页面上的内容,那个东西就是 JavaScript 通过 DOM 到达页面。这章讲的就是这种到达:JavaScript 如何找到页面的各个部分并改变它们,使页面在阅读者面前更新。
什么是 DOM
当浏览器加载你的页面时,它读取你的 HTML 并从中构建一个**对象树**:一个用于页面的对象,一个用于 <body> 的对象,一个用于里面的每个标题、段落和按钮。这个树就是 DOM,是 Document Object Model 的缩写。你的 JavaScript 可以读取这个树并改变它,当它这样做时,你看到的页面会立即更新。
值得记住的部分是:DOM 不是你的 HTML 文件。它是页面的活动版本,位于浏览器的内存中。你的 .html 文件是起始配方;DOM 是浏览器正在提供的完成的菜肴,JavaScript 可以在每个人还在吃的时候重新整理盘子。
DOM 中的每个元素都是一个对象,与你在 objects 中遇到的类型相同,拥有你可以读取和改变的属性。这就是全部技巧:因为页面是对象,而你已经知道如何处理对象,改变页面就是改变对象属性。
选择元素
在你能改变一个元素之前,你必须在树中找到它。你用选择器——与 CSS 相同的方式——指向它,浏览器给你返回匹配的对象。
主力是 document.querySelector。你给它一个**CSS 选择器**,你在 CSS 中使用的相同类型的模式,它返回第一个匹配的元素:
const card = document.querySelector(".card"); // class="card" 的第一个元素
const total = document.querySelector("#total"); // id="total" 的元素.card 按类匹配,#total 按 id 匹配,像 "button" 这样的普通词按标签名匹配。querySelector 给你第一个匹配并在那里停止。当你想要每一个匹配时,改用 querySelectorAll,它返回一个你可以循环的列表:
const cards = document.querySelectorAll(".card"); // 所有 class="card" 的元素
console.log(cards.length); // 它找到了多少个如果没有匹配,querySelector 返回 null,这是 JavaScript 说"这里没有任何东西"的方式。
document.querySelector 一个 CSS 选择器如 .card 或 #total,它给你第一个匹配。当你想要所有匹配时使用 querySelectorAll 作为一个列表。如果没有匹配你得到 null,这意味着"这里没有任何东西"。 读取和改变元素
一旦你持有一个元素,你通过它的属性读取和改变它,与你读取和改变任何对象的方式相同。这是页面开始真正移动的地方。
你会使用最多的属性是 textContent,元素内的文本。你可以读它或设置它:
const total = document.querySelector("#total");
total.textContent = "42 items"; // 页面现在显示"42 items"要改变某些东西的外观,你通常添加或移除一个类并让 CSS 做样式。classList 有三个方法:
const card = document.querySelector(".card");
card.classList.add("selected"); // 添加一个类
card.classList.remove("selected"); // 移除它
card.classList.toggle("selected"); // 如果缺失则添加,如果存在则移除你也可以通过 .style 直接设置单个样式,并用 setAttribute 设置像 src 或 href 这样的属性:
card.style.color = "crimson"; // 一个内联样式
const avatar = document.querySelector(".avatar");
avatar.setAttribute("src", "beijing.jpg"); // 设置图像源首先选择 classList 和仅用 .style 做一次性调整,因为保持你的样式在 CSS 中保持它在一个地方。
textContent 设置元素内的文本,并通过用 classList.add、remove 和 toggle 添加或移除类来改变它的外观。用 .style 做一次性调整,用 setAttribute 做像图像源这样的事。依靠类使你的样式保留在你的 CSS 中。 创建和移除元素
改变已经存在的元素会走得很远,但有时那里还没有任何东西:你添加的一个待办事项,一个到达的搜索结果。为此你构建新元素并把它们放入树中,并取出旧的。
你用 document.createElement 制作一个新元素,给它一些内容,然后用 append 把它加到页面:
const list = document.querySelector(".todo-list");
const item = document.createElement("li"); // 一个新的 <li>,还没有在页面上
item.textContent = "Buy oat milk"; // 给它一些文本
list.append(item); // 现在它显示,在列表的末尾来自 createElement 的新元素仅在内存中存在,直到你在某处 append 它;那是把它放在页面上的步骤。要从页面移除一个元素,在它上面调用 remove:
item.remove(); // 从页面消失document.createElement 构建一个新元素,用 textContent 给它文本,用 append 把它放在页面上。一个新元素仅在内存中生活,直到你附加它,所以那个步骤是使它显示的。要从页面移除一个,在它上面调用 remove。 DOM 从这里走向哪里
选择、读取、改变、创建和移除覆盖了大部分 JavaScript 对一个页面做的事,所有它在下面是相同的移动:在树中找一个对象并改变它的属性。因为 DOM 是对象,你在 objects 中学到的一切直接应用于这里,这章中的小工具集(querySelector、textContent、classList、createElement、append)是大部分工具箱。
到目前为止缺少的是时序。这里的每个例子都运行一次,从上到下,但一个真实的页面改变以响应阅读者做的:一个点击、一个按键、一个提交的表单。把你的 DOM 改变接线到那些时刻是 events,下一章,其中 addEventListener 连接"用户做了这个"到"所以页面做了那个"。一旦选择和改变坐在响应事件旁边,你可以构建本手册其余部分针对的交互页面。

