首页 / 资讯中心 / 文章详情

The JavaScript Way:用 JavaScript 修改网页结构、内容与样式的完整实战指南

The JavaScript Way:用 JavaScript 修改网页结构、内容与样式的完整实战指南 ★ FEATURED ARTICLE
教程文档【免费下载链接】thejswayThe JavaScript Way book项目地址https://gitcode.com/gh_mirrors/th/thejsway点击查看免费下载本篇对应《The JavaScript Way》第 15 章Create interactive web pages 系列第 4 篇。浏览器加载完 HTML 后JavaScript 依然可以通过 DOM API 继续改造页面修改已有元素的内容与样式、动态创建并插入新节点、替换或删除旧节点。读完本文你将掌握innerHTML、textContent、classList、setAttribute()、createElement()、appendChild()、insertBefore()、insertAdjacentHTML()、replaceChild()、removeChild()、style与getComputedStyle()等一整套 DOM 修改 API并能在真实页面中写出结构清晰、性能友好的动态更新代码。本章导读与前置知识在开始修改之前先回顾《The JavaScript Way》的 DOM 学习路线这对理解本篇文章的位置很有帮助第 13 章 介绍了 DOM 树的基本概念页面是一棵由元素节点与文本节点构成的树document变量指向树根childNodes、parentNode、nodeType等属性负责逐节点遍历第 14 章 解决了怎么快速找到要操作的元素的问题getElementById()、getElementsByTagName()、getElementsByClassName()、querySelector()、querySelectorAll()等选择方法其中 querySelector/querySelectorAll 使用 CSS 选择器本章则聚焦**找到之后如何改**无论是修改已有元素的内容、属性、类名与样式还是凭空创建一个新元素插入页面都属于 DOM 修改Modify page structure的范畴后续 第 16 章 将在此基础上引入事件监听如addEventListener()让页面能响应用户点击等操作动态修改的技术基础正是本章内容。示例页面贯穿全章的编程语言列表本章绝大部分示例都基于下面这段 HTML。它包含一个标题和一个ul无序列表列表里有 C、Java、C#、PHP 四种语言h3 classbeginningSome languages/h3 div idcontent ul idlanguages li idcppC/li li idjavaJava/li li idcsharpC#/li li idphpPHP/li /ul /div你可以把这段代码保存为 HTML 文件在浏览器中打开并打开开发者工具的控制台Console逐条运行后面的 JavaScript 示例观察页面变化——注意示例之间可能存在叠加效果建议按顺序执行或刷新页面后再试。修改已有元素上一章学到的 DOM 遍历与选择属性/方法同样可以用来更新页面中的元素。用 innerHTML 修改 HTML 内容innerHTML属性可以读取或改写元素内部的 HTML 内容。向列表追加一个新条目可以用运算符拼接 HTML 字符串——下面这行代码先通过getElementById(languages)选中ul再在列表末尾追加一个li// Modifying an HTML element: adding an li document.getElementById(languages).innerHTML li idcC/li;innerHTML最常见的另一个用途是清空内容——把它赋值为空字符串即可删除元素内部所有子节点// Delete the HTML content of the list, replacing it with nothing document.getElementById(languages).innerHTML ;在继续之前请把这行代码从你的程序中移除否则列表就空了后续示例将无处施展!!! tip 建议使用 innerHTML 时HTML 内容是以**字符串**形式写入的。为了保持代码可读、避免拼接出错建议只在改动**较小**的内容时使用 innerHTML。下面你会看到更灵活、更安全的解决方案。值得一提的是上一章已经介绍过innerHTML的读取能力——第 14 章用它输出元素内部的 HTML 源码本章则演示了它的写入能力读写两端合起来才算完整掌握该属性。另外需要留意innerHTML不是 W3C DOM 规范的一部分由微软提出但如今所有主流浏览器都支持它。用 textContent 修改文本内容与innerHTML处理 HTML 字符串不同textContent属性用于修改元素的纯文本内容。下面的代码选中页面第一个h3标题在其现有文本后追加一段文字// Modify the titles text content document.querySelector(h3).textContent for programming;执行后标题从 Some languages 变为 Some languages for programming。注意textContent会把内容当作纯文本处理即使用户输入包含、之类的字符也不会被解析成 HTML因此在处理用户输入、避免注入风险时textContent往往比innerHTML更安全、更合适。修改元素属性setAttribute() 与属性直接赋值setAttribute()方法可以为元素设置任意属性的值参数依次是属性名和属性值// Define the id attribute of the first title document.querySelector(h3).setAttribute(id, title);如第 14 章所见部分常用属性如id、href、value在 DOM 中同时以对象属性的形式存在可以直接赋值效果与setAttribute()相同// Define the id attribute of the first title document.querySelector(h3).id title;两种写法等价。对于id这类常见属性直接赋属性值更简洁setAttribute()则胜在通用——它可以处理任意属性包括data-*自定义属性等。用 classList 增删类名一个元素可以同时拥有多个 class。classList属性返回该元素的类名集合并提供了add()/remove()等方法。下面代码把第一个h3的beginning类移除、再加上title类并把元素打印到控制台const titleElement document.querySelector(h3); // Grab the first h3 titleElement.classList.remove(beginning); // Remove the class beginning titleElement.classList.add(title); // Add a class called title console.log(titleElement);上一章还介绍过classList的查询能力contains()判断是否包含某类、length与下标访问遍历类名本章的add()/remove()则是它的写入能力。此外classList还内置toggle()等方法可结合 第 14 章 的内容一并掌握。添加新元素三步走修改已有元素之外更常见的是凭空创建一个新元素并插入页面。整个过程可以拆成三步创建新元素设置元素属性ID、类、文本内容等把新元素插入DOM 树。例如给语言列表添加一门 Pythonconst pythonElement document.createElement(li); // Create an li element pythonElement.id python; // Define element ID pythonElement.textContent Python; // Define its text content document.getElementById(languages).appendChild(pythonElement); // Insert the new element into the DOM下面逐一步骤拆解。第 1 步createElement() 创建元素createElement()方法用于创建元素节点。它在document对象上调用参数是新元素的标签名返回值是创建好的元素对象DOM 中它尚未挂载到任何位置只是一个游离节点const pythonElement document.createElement(li); // Create an li element第 2 步设置元素属性元素创建后就可以利用前面学的 DOM 属性给它填充细节——ID、class、文本内容等等。示例中把新元素的 ID 设为python、文本内容设为Python// ... pythonElement.id python; // Define element ID pythonElement.textContent Python; // Define its text content这里也可以改用setAttribute()或classList.add()取决于你想设置的属性类型。第 3 步appendChild() 插入 DOM把新节点挂到 DOM 树上的技术有多种最常用的是appendChild()在未来父元素上调用它新节点会被追加为该父元素最后一个子节点// ... document.getElementById(languages).appendChild(pythonElement); // Insert the new element into the DOM在我们的例子中pythonElement成为ul idlanguages的新子节点排在 C、Java、C#、PHP 之后。添加元素的更多变体appendChild()是追加到末尾的标准方案但实际需求往往更复杂有时只想加纯文本、有时要插到指定位置。本章提供了三种补充方案。createTextNode()添加纯文本节点不想用textContent属性也可以先创建文本节点再挂载。createTextNode()创建文本节点再用appendChild()把它挂到元素上。下面的代码用这种方式在列表末尾插入 Rubyconst rubyElement document.createElement(li); // Create an li element rubyElement.id ruby; // Define element ID rubyElement.appendChild(document.createTextNode(Ruby)); // Define its text content document.getElementById(languages).appendChild(rubyElement); // Insert the new element into the DOM注意这里的双重appendChild()第一个把文本节点挂进li第二个把li挂进ul。回想第 13 章提到的文本节点是 DOM 树中与元素节点平级的一类节点见 chapter13.mdcreateTextNode()正是程序化生成这类节点的方法。insertBefore()插到指定节点之前当追加到末尾不满足需求时可以用insertBefore()。在父元素上调用参数依次是新节点和参照节点新节点会被插入到参照节点之前。例如把 Perl 插到 PHP 前面const perlElement document.createElement(li); // Create an li element perlElement.id perl; // Define element ID perlElement.textContent Perl; // Define its text content // Insert the new element before the PHP node document.getElementById(languages).insertBefore(perlElement, document.getElementById(php));insertBefore(newNode, referenceNode)与appendChild(newNode)的参数顺序相反使用时务必区分前者把节点放在参照节点之前后者把节点放在父元素子节点列表的末尾。insertAdjacentHTML()精确控制插入位置insertAdjacentHTML()可以更精确地指定插入位置。调用方式是在已有元素上调用传入两个参数位置和一段HTML 字符串。位置取值共有四种位置含义beforebegin插入到该元素之前作为其兄弟节点afterbegin插入到该元素内部、其第一个子节点之前beforeend插入到该元素内部、其最后一个子节点之后afterend插入到该元素之后作为其兄弟节点以现有p标签为例四个位置对应关系如下!-- beforebegin -- p !-- afterbegin -- foo !-- beforeend -- /p !-- afterend --实际使用中位置参数不区分大小写文档示例用的是afterBegin。下面的代码把 JavaScript 插入到语言列表的顶部即ul第一个子节点之前// Add an element to the beginning of a list document.getElementById(languages).insertAdjacentHTML(afterBegin, li idjavascriptJavaScript/li);与createElement()appendChild()相比insertAdjacentHTML()直接接收 HTML 字符串、一步完成插入代码更简短代价与innerHTML类似——字符串拼接过多会降低可读性且需要留意 HTML 解析带来的开销与安全边界。替换与删除节点replaceChild()替换节点replaceChild()用新节点替换父元素的某个子节点参数顺序是新节点, 被替换节点。下面的代码把 Perl 替换成 Lispconst lispElement document.createElement(li); // Create an li element lispElement.id lisp; // Define its ID lispElement.textContent Lisp; // Define its text content // Replace the element identified by perl with the new element document.getElementById(languages).replaceChild(lispElement, document.getElementById(perl));参数顺序容易记混新节点在前、旧节点在后与insertBefore(newNode, referenceNode)的新节点在前风格一致。removeChild()删除节点删除节点使用removeChild()参数是要被移除的节点通常先用选择方法拿到它// Remove the element with the lisp id document.getElementById(languages).removeChild(document.getElementById(lisp));执行后列表恢复为 C、Java、C#、PHP、C、Ruby、Perl(已被替换为 Lisp 又被删除)、JavaScript 的中间状态——这正是各示例顺序执行时页面呈现的效果。修改元素样式JavaScript 不仅能改页面结构还能改元素的视觉样式。下面是样式部分的示例 HTML 与配套 CSS。示例 HTML三个段落第二个通过内联style属性设为绿色pFirst/p p stylecolor: green;Second/p p idparaThird/p配套 CSS 样式表#para的文本为蓝色且倾斜#para { font-style: italic; color: blue; }style 属性修改内联样式每个 DOM 元素都有一个style属性它返回一个代表元素内联style属性的对象对象上的各属性与 CSS 属性一一对应。给这些属性赋值就等于直接修改元素的样式。例如选中第一个段落并修改其文字颜色与外边距const paragraphElement document.querySelector(p); paragraphElement.style.color red; paragraphElement.style.margin 50px;复合 CSS 属性的 camelCase 命名部分 CSS 属性由多个单词组成如background-color。在 JavaScript 中访问这类属性时需要去掉连字符并把后续单词首字母大写camelCase 驼峰命名法。下面的代码把同一个段落的font-family与background-color分别设为 Arial 和黑色// ... paragraphElement.style.fontFamily Arial; paragraphElement.style.backgroundColor black;这种命名约定在本书此前章节中已经出现过CSS 的background-color对应 JS 的backgroundColorfont-family对应fontFamily规律完全一致。各 CSS 属性对应的 JavaScript 属性名可查阅 Mozilla Developer Network 的 CSS Properties Reference 文档。style 属性的局限读不到样式表里的样式style属性只反映元素内联style属性中声明的样式无法读取定义在 CSS 样式表中的样式。试着读取三个段落的文字颜色const paragraphElements document.getElementsByTagName(p); console.log(paragraphElements[0].style.color); // red console.log(paragraphElements[1].style.color); // green console.log(paragraphElements[2].style.color); // Show an empty string前两个段落分别返回red和green——因为它们的内联样式被 JavaScript 或 HTML 显式设置了第三个段落的蓝色来自外部 CSS 样式表#para规则style属性对它一无所知返回空字符串。getComputedStyle()读取最终计算样式要读取元素最终生效的样式包括样式表规则、继承结果应使用getComputedStyle()。它以 DOM 节点为参数返回一个代表该元素计算样式computed style的对象之后即可读取各 CSS 属性const paragraphStyle getComputedStyle(document.getElementById(para)); console.log(paragraphStyle.fontStyle); // italic console.log(paragraphStyle.color); // color blue in RGB values这里的蓝色以 RGB 形式呈现红、绿、蓝三个通道的取值都在 0 到 255 之间。需要强调的是getComputedStyle()返回的对象是只读的——它用于读取元素当前实际样式要修改样式依然靠style属性或classList操作类名让 CSS 规则生效。DOM 操作与性能每次通过 JavaScript 更新 DOM浏览器都需要重新计算页面的显示效果包括重新布局与重绘。频繁的 DOM 操作会导致页面卡顿、性能下降因此应尽可能减少 DOM 的访问与更新次数。一个典型的性能优化习惯是先把新元素的属性设置好再一次性插入 DOM。对比下面两种写法// Bad: DOM is updated multiple times const newNode document.createElement(...); // Create new element parentNode.appendChild(newNode); // Add it to the DOM newNode.id ...; // Set some element properties newNode.textContent ...; // ... // Better: DOM is updated only once const newNode document.createElement(...); // Create new element newNode.id ...; // Set some element properties newNode.textContent ...; // ... parentNode.appendChild(newNode); // Add it to the DOM左侧写法先插入、后设置属性浏览器被迫在元素插入后再次为属性变化重新计算渲染右侧写法先在游离状态下把所有属性配齐再一次性挂载DOM 只被更新一次。这也正是本章添加新元素三步走先创建、再设置、后插入的顺序如此安排的深层原因——它不仅是逻辑清晰更是性能友好的实践。快速回顾TL;DR本章知识要点一览修改一个 DOM 元素的信息可以使用innerHTML、textContent、classList等属性以及setAttribute()方法创建新的 DOM 节点用createTextNode()文本节点与createElement()元素节点appendChild()把新节点插入为某元素的最后一个子节点insertBefore()与insertAdjacentHTML()是插入内容的另外两种方式分别支持插到指定节点之前与四种精确位置replaceChild()替换已有节点removeChild()删除节点JavaScript 的style属性代表 DOM 节点的内联style属性可用于修改样式多单词 CSS 属性在 JavaScript 中写成camelCase例如font-family→fontFamilystyle属性不适合用来读取元素样式读取请使用getComputedStyle()DOM 操作应克制进行避免拖慢页面性能。实战练习以下是本章配套练习建议在浏览器控制台或独立 HTML 页面中完成逐一验证输出结果。练习 1添加一个段落在语言列表示例的基础上向页面添加一个段落p段落内包含一个指向编程语言列表页面https://en.wikipedia.org/wiki/List_of_programming_languages的超链接a。提示用createElement()分别创建p与a设置a.href与文本内容再通过appendChild()依次挂载。练习 2报纸列表给定如下 HTML 页面h3Some newspapers/h3 div idcontent/div编写程序把下面数组中定义的报纸以可点击链接的形式显示在页面上// Newspaper list const newspapers [https://www.nytimes.com, https://www.washingtonpost.com, http://www.economist.com];思路遍历数组为每项创建a元素textContent用报纸名、href用 URL再插入#content。注意观察用innerHTML拼接与用createElement()appendChild()两种写法的差异。练习 3迷你词典给定如下 HTML 页面h3A mini-dictionary/h3 div idcontent/div编写程序把下面数组中的词条以术语 定义列表的形式显示在页面上const words [{ term: Procrastination, definition: Avoidance of doing a task that needs to be accomplished }, { term: Tautology, definition: logical argument constructed in such a way that it is logically irrefutable }, { term: Oxymoron, definition: figure of speech that juxtaposes elements that appear to be contradictory }];要求使用 HTML 的dl描述列表标签组织内容可参考 MDN 上关于dl标签的文档并且每个术语用strong标签加粗强调。dl内通常包含dt术语与dd定义两类子元素注意createElement()只能逐个创建标签需要你为每个词条创建两个子元素。练习 4更新颜色给定包含三个标题与三个正文段落的 HTML 页面每对h1div构成一个小节。编写程序首先通过prompt()询问用户新的文字颜色再通过prompt()询问新的背景颜色页面中所有段落随之更新。思路用querySelectorAll()或getElementsByTagName()选中所有div遍历并为每个元素设置style.color与style.backgroundColor——注意background-color在 JavaScript 中要写成backgroundColor。练习 5获取元素的信息给定如下 HTML 与 CSSdiv idcontentABC brEasy as brOne, two, three /div div idinfos/div#content { float: right; margin-top: 100px; margin-right: 50px; }编写程序在#infos中显示#content元素的高度与宽度。这里无法用style属性读取尺寸由 CSS 样式表与内容共同决定需要借助getComputedStyle()或元素的offsetWidth/offsetHeight等布局属性来获取实际渲染尺寸。完成以上练习后你就完整走通了选择元素 → 修改内容/属性/类名 → 创建与插入新节点 → 替换与删除 → 修改样式 → 读取计算样式这条 DOM 动态化主链路。接下来的 第 16 章 将把这一切与事件监听结合让页面真正响应用户交互进入事件驱动的交互式 Web 开发阶段。赞分享教程文档【免费下载链接】thejswayThe JavaScript Way book项目地址https://gitcode.com/gh_mirrors/th/thejsway点击查看免费下载相关推荐The JavaScript Way 实战项目用 DOM 与事件构建 PubLink 社交新闻网页The JavaScript Way 实战项目用 DOM 与事件构建 PubLink 社交新闻网页 本篇文章是《The JavaScript Way》开源书中教程文档网页开发入门The JavaScript Way 中的 HTML、CSS 与 JavaScript 三大语言指南网页开发入门The JavaScript Way 中的 HTML、CSS 与 JavaScript 三大语言指南 本篇文章以开源书籍 The JavaScri教程文档The JavaScript Way 第八章精讲JavaScript 字符串处理的完整实战指南The JavaScript Way 第八章精讲JavaScript 字符串处理的完整实战指南 本文基于开源书籍《The JavaScript Way》的 m教程文档上一篇智能视频格式转换终极方案解锁B站缓存视频的全平台播放能力下一篇英雄联盟Akari助手3大核心功能彻底改变你的游戏体验创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站