JavaScript 基础
Document
运算符
深入数据和类型
函数进阶
原型、继承
类
浏览器存储
Web API
事件
错误处理
异步编程
网络请求
模块
练习
实例
工具与规范
软件架构模式
设计模式
DOM 操作
DOM 的全称是 Document Object Model(文档对象模型),相当于把页面的内容映射成了一个对象,通过 DOM 我们可以获取并修改页面上的任何内容。
本章节的内容就是对如何获取与修改页面元素有一个初步的了解。
获取元素
一般我们获取元素有两个步骤:
- HTML 中设置元素的
id
属性。 - JavaScript 中通过
document.getElementById()
方法获取元素。
点击实例中的 执行代码
并查看控制台中的输出,在实例中的 HTML 定义了一个 p 元素并设置 id 为 title,还定义了一个按钮绑定了点击事件,当点击时通过 document.getElementById()
获取元素并打印到控制台中。
<iframe height="300" style="width: 100%" scrolling="no" title="演示" src="https://codepen.io/3yya/embed/XWVPzLB?default-tab=js%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
通过 document.getElementById()
方法获取到的是一个元素对象,便可以通过操作此元素对象获取或修改元素内容。
获取或修改元素内 HTML
innerHTML
属性可以通过 HTML 代码的形式获取或修改元素内 HTML 内容。
实例中定义了绑定了两个按钮事件,一个在点击时获取元素的内容并通过 alert 输出,另一个则修改元素内的 HTML 代码为一个 img 元素。
<iframe height="300" style="width: 100%" scrolling="no" title="演示" src="https://codepen.io/3yya/embed/abEaEKo?default-tab=js%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
获取或修改元素 HTML
outerHTML
与 innerHTML
的区别在于, outerHTML
属性获取或修改的元素 HTML 内容包括了自身。因此当修改 outerHTML
的内容时就相当于替换了一个新的元素。
实例中修改元素的 outerHTML
时将自身也替换掉了。
<iframe height="300" style="width: 100%" scrolling="no" title="演示" src="https://codepen.io/3yya/embed/qBpMpLO?default-tab=js%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
获取或修改元素内文本
textContent
属性获取的是元素内所有的纯文本内容,不包括标签或属性。当设置 textContent
属性时,设置的值也会被当作纯文本内容。
实例中获取 textContent 时仅输出了纯文本,并且修改的 img HTML 代码并没有生效,原因是这些代码被当成了纯文本对待。
<iframe height="300" style="width: 100%" scrolling="no" title="演示" src="https://codepen.io/3yya/embed/oNpPpRz?default-tab=js%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
获取或修改 input 的值
对于 input
元素,可以通过 value
属性获取或修改其值。
实例中定义了一个输入框,并绑定了三个按钮事件:
- 获取用户名:输出元素的 value 值
- 默认用户名:将元素的 value 值设置为 三眼鸭
- 清空用户名:将元素的 value 值设置为空字符串
<iframe height="300" style="width: 100%" scrolling="no" title="演示" src="https://codepen.io/3yya/embed/OJzoQNE?default-tab=js%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
计算器实例
以下代码演示了一个加法计算器的实例。
<iframe height="300" style="width: 100%" scrolling="no" title="演示" src="https://codepen.io/3yya/embed/xxpaWza?default-tab=js%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>
练习
- 使用 JavaScript 代码在页面上显示以下题库内容。
// 题库
let items = [
{
question: "中国的首都是?",
answers: ["上海", "广州", "北京"],
rightIdx: 2,
},
{
question: "美国的首都是?",
answers: ["纽约", "华盛顿", "伦敦"],
rightIdx: 1,
},
{
question: "新加坡的首都是?",
answers: ["后港", "新加坡市", "裕华"],
rightIdx: 1,
},
{
question: "越南的首都是?",
answers: ["河内", "胡志明市", "海防"],
rightIdx: 0,
},
{
question: "印度的首都是?",
answers: ["新德里", "巴黎", "孟买"],
rightIdx: 0,
},
]
$$demo <div id="container" class="container"> <!-- <h3>中国的首都是?</h3> <div class="options"> <div>上海</div> <div>广州</div> <div>北京</div> </div> --> </div> <style> .container { display: flex; flex-direction: column;
align-items: center;
}
.options {
display: flex;
gap: 20px;
}
</style> <script> // 题库 let items = [ { question: "中国的首都是?", answers: ["上海", "广州", "北京"], rightIdx: 2, }, { question: "美国的首都是?", answers: ["纽约", "华盛顿", "伦敦"], rightIdx: 1, }, { question: "新加坡的首都是?", answers: ["后港", "新加坡市", "裕华"], rightIdx: 1, }, { question: "越南的首都是?", answers: ["河内", "胡志明市", "海防"], rightIdx: 0, }, { question: "印度的首都是?", answers: ["新德里", "巴黎", "孟买"], rightIdx: 0, }, ]
// container 元素
let container = document.getElementById("container")
for (let item of items) {
container.innerHTML += `
<h3>${item.question}</h3>
<div class="options">
<div>${item.answers[0]}</div>
<div>${item.answers[1]}</div>
<div>${item.answers[2]}</div>
</div>
`
}
</script> $$
$$answer
<div id="container" class="container">
<!-- <h3>中国的首都是?</h3>
<div class="options">
<div>上海</div>
<div>广州</div>
<div>北京</div>
</div> -->
</div>
<style>
.container {
display: flex;
flex-direction: column;
align-items: center;
}
.options {
display: flex;
gap: 20px;
}
</style>
<script>
// 题库
let items = [
{
question: "中国的首都是?",
answers: ["上海", "广州", "北京"],
rightIdx: 2,
},
{
question: "美国的首都是?",
answers: ["纽约", "华盛顿", "伦敦"],
rightIdx: 1,
},
{
question: "新加坡的首都是?",
answers: ["后港", "新加坡市", "裕华"],
rightIdx: 1,
},
{
question: "越南的首都是?",
answers: ["河内", "胡志明市", "海防"],
rightIdx: 0,
},
{
question: "印度的首都是?",
answers: ["新德里", "巴黎", "孟买"],
rightIdx: 0,
},
]
// container 元素
let container = document.getElementById("container")
for (let item of items) {
container.innerHTML += `
<h3>${item.question}</h3>
<div class="options">
<div>${item.answers[0]}</div>
<div>${item.answers[1]}</div>
<div>${item.answers[2]}</div>
</div>
`
}
</script>
$$ 2. 补充实例,使得正确答案能够高亮。 $$demo <div id="container" class="container"> <!-- <h3>中国的首都是?</h3> <div class="options"> <div>上海</div> <div>广州</div> <div>北京</div> </div> --> </div> <style> .container { display: flex; flex-direction: column;
align-items: center;
}
.options {
display: flex;
gap: 20px;
}
.right {
font-weight: bold;
color: #67c23a;
}
</style> <script> // 题库 let items = [ { question: "中国的首都是?", answers: ["上海", "广州", "北京"], rightIdx: 2, }, { question: "美国的首都是?", answers: ["纽约", "华盛顿", "伦敦"], rightIdx: 1, }, { question: "新加坡的首都是?", answers: ["后港", "新加坡市", "裕华"], rightIdx: 1, }, { question: "越南的首都是?", answers: ["河内", "胡志明市", "海防"], rightIdx: 0, }, { question: "印度的首都是?", answers: ["新德里", "巴黎", "孟买"], rightIdx: 0, }, ]
// container 元素
let container = document.getElementById("container")
let htmlStr = ""
for (let item of items) {
htmlStr += `<h3>${item.question}</h3>`
htmlStr += '<div class="options">'
for (let idx in item.answers) {
if (idx == item.rightIdx) {
// 如果是正确答案
htmlStr += `<div class="right">${item.answers[idx]}</div>`
} else {
htmlStr += `<div>${item.answers[idx]}</div>`
}
}
htmlStr += "</div>"
}
container.innerHTML = htmlStr
</script> $$
$$answer
<div id="container" class="container">
<!-- <h3>中国的首都是?</h3>
<div class="options">
<div>上海</div>
<div>广州</div>
<div>北京</div>
</div> -->
</div>
<style>
.container {
display: flex;
flex-direction: column;
align-items: center;
}
.options {
display: flex;
gap: 20px;
}
.right {
font-weight: bold;
color: #67c23a;
}
</style>
<script>
// 题库
let items = [
{
question: "中国的首都是?",
answers: ["上海", "广州", "北京"],
rightIdx: 2,
},
{
question: "美国的首都是?",
answers: ["纽约", "华盛顿", "伦敦"],
rightIdx: 1,
},
{
question: "新加坡的首都是?",
answers: ["后港", "新加坡市", "裕华"],
rightIdx: 1,
},
{
question: "越南的首都是?",
answers: ["河内", "胡志明市", "海防"],
rightIdx: 0,
},
{
question: "印度的首都是?",
answers: ["新德里", "巴黎", "孟买"],
rightIdx: 0,
},
]
// container 元素
let container = document.getElementById("container")
let htmlStr = ""
for (let item of items) {
htmlStr += `<h3>${item.question}</h3>`
htmlStr += '<div class="options">'
for (let idx in item.answers) {
if (idx == item.rightIdx) {
// 如果是正确答案
htmlStr += `<div class="right">${item.answers[idx]}</div>`
} else {
htmlStr += `<div>${item.answers[idx]}</div>`
}
}
htmlStr += "</div>"
}
container.innerHTML = htmlStr
</script>
$$
- 实现以下简易计算器实例效果。
$$demo <body> <input id="num1" type="number" placeholder="第一个数" /> <select id="operator"> <option value="plus">+</option> <option value="sub">-</option> <option value="mult">*</option> <option value="divide">/</option> </select> <input id="num2" type="number" placeholder="第二个数" /> <button onclick="calc()">=</button> <span id="result"></span> </body>
<script> function calc() { let num1 = Number(document.getElementById("num1").value) let num2 = Number(document.getElementById("num2").value)
let op = document.getElementById("operator").value
let result
switch (op) {
case "plus":
result = num1 + num2
break
case "sub":
result = num1 - num2
break
case "mult":
result = num1 * num2
break
case "divide":
result = num1 / num2
break
}
document.getElementById("result").textContent = result
}
</script> $$
$$answer
<input id="num1" type="number" placeholder="第一个数" />
<select id="operator">
<option value="plus">+</option>
<option value="sub">-</option>
<option value="mult">*</option>
<option value="divide">/</option>
</select>
<input id="num2" type="number" placeholder="第二个数" />
<button onclick="calc()">=</button>
<span id="result"></span>
<script>
function calc() {
let num1 = Number(document.getElementById("num1").value)
let num2 = Number(document.getElementById("num2").value)
let op = document.getElementById("operator").value
let result
switch (op) {
case "plus":
result = num1 + num2
break
case "sub":
result = num1 - num2
break
case "mult":
result = num1 * num2
break
case "divide":
result = num1 / num2
break
}
document.getElementById("result").textContent = result
}
</script>
$$
-
完成以下点击放大元素的效果。 $$demo <div id="box" class="box" onclick="enlarge()">点我变大</div> <style> .box { cursor: pointer;
display: flex; align-items: center; justify-content: center; background-color: teal; color: white; font-weight: bold; width: 5em; height: 5em; border: 1em solid pink; /* 禁止文本被选中 */ user-select: none;
} </style> <script> // 以字体大小为基准 // 默认字体大小 1em // 每次点击放大到 1.2 倍 let factor = 1
function refresh() { let box = document.getElementById("box") box.outerHTML =
<div id="box" class="box" onclick="enlarge()" style="font-size: ${factor}em" > 点我变大 </div>
}function enlarge() { // 放大到 1.2 倍 factor *= 1.2
// 更新 box refresh()
} </script> $$
$$answer
<div id="box" class="box" onclick="enlarge()">点我变大</div>
<style>
.box {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
background-color: teal;
color: white;
font-weight: bold;
width: 5em;
height: 5em;
border: 1em solid pink;
/* 禁止文本被选中 */
user-select: none;
}
</style>
<script>
// 以字体大小为基准
// 默认字体大小 1em
// 每次点击放大到 1.2 倍
let factor = 1
function refresh() {
let box = document.getElementById("box")
box.outerHTML = `
<div
id="box"
class="box"
onclick="enlarge()"
style="font-size: ${factor}em"
>
点我变大
</div>
`
}
function enlarge() {
// 放大到 1.2 倍
factor *= 1.2
// 更新 box
refresh()
}
</script>
$$
- 使用题库完成以下答题实例。
// 题库
let items = [
{
question: "中国的首都是?",
answers: ["上海", "广州", "北京"],
rightIdx: 2,
},
{
question: "美国的首都是?",
answers: ["纽约", "华盛顿", "伦敦"],
rightIdx: 1,
},
{
question: "新加坡的首都是?",
answers: ["后港", "新加坡市", "裕华"],
rightIdx: 1,
},
{
question: "越南的首都是?",
answers: ["河内", "胡志明市", "海防"],
rightIdx: 0,
},
{
question: "印度的首都是?",
answers: ["新德里", "巴黎", "孟买"],
rightIdx: 0,
},
]
$$demo <div id="container" class="container"> <!-- <h2>中国的首都是?</h2> <div class="options"> <div class="btn" onclick="choose()">上海</div> <div class="btn" onclick="choose()">广州</div> <div class="btn" onclick="choose()">北京</div> </div> --> <!-- <h2 class="right">答对了</h2> <div class="btn" onclick="next()">下一题</div> --> <!-- <h2 class="wrong">答错了,正确答案是北京</h2> <div class="btn" onclick="next()">下一题</div> --> <!-- <h2>答题结果</h2> <p>总共 5 题,答对了 2 题。</p> <div class="btn" onclick="restart()">重新答题</div> --> </div> <style> /* 全用 flex / .container { display: flex; / 垂直 / flex-direction: column; / 交叉轴居中 */ align-items: center; }
.options {
display: flex;
/* 子项间的间距 */
gap: 20px;
}
.btn {
padding: 5px 20px;
border-radius: 8px;
font-weight: bold;
/* 小手光标样式 */
cursor: pointer;
}
.btn:hover {
background-color: #eee;
}
.right {
color: #6ac244;
}
.wrong {
color: #f36a6e;
}
</style> <script> // 题库 let items = [ { question: "中国的首都是?", answers: ["上海", "广州", "北京"], rightIdx: 2, }, { question: "美国的首都是?", answers: ["纽约", "华盛顿", "伦敦"], rightIdx: 1, }, { question: "新加坡的首都是?", answers: ["后港", "新加坡市", "裕华"], rightIdx: 1, }, { question: "越南的首都是?", answers: ["河内", "胡志明市", "海防"], rightIdx: 0, }, { question: "印度的首都是?", answers: ["新德里", "巴黎", "孟买"], rightIdx: 0, }, ]
// 开发步骤:
// 1. 拆解项目、功能。
// 2. 把 HTML、CSS 部分先写出来。
// 3. 逐步实现 JS 功能。
// 功能:
// 1. 显示题目答案。
// 2. 有选中题目的交互、功能。
// 3. 显示对错的结果。
// 4. 循环以上功能。
// 5. 最后一题答完后,显示总的结果与重新答题。
let container = document.getElementById("container")
console.log(container)
// 当前的题目下标
let currentIdx = 0
// 答对的题数
let rightCount = 0
// 更新题目
refresh()
function next() {
// 下一步
if (currentIdx === items.length - 1) {
console.log("最后一题")
// 最后一题
container.innerHTML = `
<h2>答题结果</h2>
<p>总共 ${items.length} 题,答对了 ${rightCount} 题。</p>
<div class="btn" onclick="restart()">重新答题</div>
`
} else {
console.log("不是最后一题")
// 切换下一题
currentIdx++
// 更新题目
refresh()
}
}
function refresh() {
// 更新题目的内容
container.innerHTML = `
<h2>${items[currentIdx].question}</h2>
<div class="options">
<div class="btn" onclick="choose(0)">${items[currentIdx].answers[0]}</div>
<div class="btn" onclick="choose(1)">${items[currentIdx].answers[1]}</div>
<div class="btn" onclick="choose(2)">${items[currentIdx].answers[2]}</div>
</div>
`
}
function choose(chooseIdx) {
// 选中答案
console.log(`选中答案:${chooseIdx}`)
// 与正确答案进行比较
if (chooseIdx === items[currentIdx].rightIdx) {
// 答对计数
rightCount++
container.innerHTML = `
<h2 class="right">答对了</h2>
<div class="btn" onclick="next()">${
currentIdx === items.length - 1 ? "完成" : "下一题"
}</div>
`
} else {
// 正确答案的下标:items[currentIdx].rightIdx
// 通过下标去拿正确答案
let answer = items[currentIdx].answers[items[currentIdx].rightIdx]
container.innerHTML = `
<h2 class="wrong">答错了,正确答案是${answer}</h2>
<div class="btn" onclick="next()">${
currentIdx === items.length - 1 ? "完成" : "下一题"
}</div>
`
}
}
function restart() {
// 重新答题
// 重置数据
// 将当前的题目下标重置为 0
currentIdx = 0
// 当前答对的题数重置为 0
rightCount = 0
// 更新题目
refresh()
}
</script>
$$
$$answer
<div id="container" class="container">
<!-- <h2>中国的首都是?</h2>
<div class="options">
<div class="btn" onclick="choose()">上海</div>
<div class="btn" onclick="choose()">广州</div>
<div class="btn" onclick="choose()">北京</div>
</div> -->
<!-- <h2 class="right">答对了</h2>
<div class="btn" onclick="next()">下一题</div> -->
<!-- <h2 class="wrong">答错了,正确答案是北京</h2>
<div class="btn" onclick="next()">下一题</div> -->
<!-- <h2>答题结果</h2>
<p>总共 5 题,答对了 2 题。</p>
<div class="btn" onclick="restart()">重新答题</div> -->
</div>
<style>
/* 全用 flex */
.container {
display: flex;
/* 垂直 */
flex-direction: column;
/* 交叉轴居中 */
align-items: center;
}
.options {
display: flex;
/* 子项间的间距 */
gap: 20px;
}
.btn {
padding: 5px 20px;
border-radius: 8px;
font-weight: bold;
/* 小手光标样式 */
cursor: pointer;
}
.btn:hover {
background-color: #eee;
}
.right {
color: #6ac244;
}
.wrong {
color: #f36a6e;
}
</style>
<script>
// 题库
let items = [
{
question: "中国的首都是?",
answers: ["上海", "广州", "北京"],
rightIdx: 2,
},
{
question: "美国的首都是?",
answers: ["纽约", "华盛顿", "伦敦"],
rightIdx: 1,
},
{
question: "新加坡的首都是?",
answers: ["后港", "新加坡市", "裕华"],
rightIdx: 1,
},
{
question: "越南的首都是?",
answers: ["河内", "胡志明市", "海防"],
rightIdx: 0,
},
{
question: "印度的首都是?",
answers: ["新德里", "巴黎", "孟买"],
rightIdx: 0,
},
]
// 开发步骤:
// 1. 拆解项目、功能。
// 2. 把 HTML、CSS 部分先写出来。
// 3. 逐步实现 JS 功能。
// 功能:
// 1. 显示题目答案。
// 2. 有选中题目的交互、功能。
// 3. 显示对错的结果。
// 4. 循环以上功能。
// 5. 最后一题答完后,显示总的结果与重新答题。
let container = document.getElementById("container")
console.log(container)
// 当前的题目下标
let currentIdx = 0
// 答对的题数
let rightCount = 0
// 更新题目
refresh()
function next() {
// 下一步
if (currentIdx === items.length - 1) {
console.log("最后一题")
// 最后一题
container.innerHTML = `
<h2>答题结果</h2>
<p>总共 ${items.length} 题,答对了 ${rightCount} 题。</p>
<div class="btn" onclick="restart()">重新答题</div>
`
} else {
console.log("不是最后一题")
// 切换下一题
currentIdx++
// 更新题目
refresh()
}
}
function refresh() {
// 更新题目的内容
container.innerHTML = `
<h2>${items[currentIdx].question}</h2>
<div class="options">
<div class="btn" onclick="choose(0)">${items[currentIdx].answers[0]}</div>
<div class="btn" onclick="choose(1)">${items[currentIdx].answers[1]}</div>
<div class="btn" onclick="choose(2)">${items[currentIdx].answers[2]}</div>
</div>
`
}
function choose(chooseIdx) {
// 选中答案
console.log(`选中答案:${chooseIdx}`)
// 与正确答案进行比较
if (chooseIdx === items[currentIdx].rightIdx) {
// 答对计数
rightCount++
container.innerHTML = `
<h2 class="right">答对了</h2>
<div class="btn" onclick="next()">${
currentIdx === items.length - 1 ? "完成" : "下一题"
}</div>
`
} else {
// 正确答案的下标:items[currentIdx].rightIdx
// 通过下标去拿正确答案
let answer = items[currentIdx].answers[items[currentIdx].rightIdx]
container.innerHTML = `
<h2 class="wrong">答错了,正确答案是${answer}</h2>
<div class="btn" onclick="next()">${
currentIdx === items.length - 1 ? "完成" : "下一题"
}</div>
`
}
}
function restart() {
// 重新答题
// 重置数据
// 将当前的题目下标重置为 0
currentIdx = 0
// 当前答对的题数重置为 0
rightCount = 0
// 更新题目
refresh()
}
</script>
$$