文章目录
一、WebAPI背景知识
1. 什么是WebAPI?
前面学习的 JS 分成三个大的部分:
ECMAScript
: 基础语法部分DOM API
: 操作页面结构BOM API
: 操作浏览器
WebAPI
就包含了 DOM
+ BOM
,这个是 W3C
组织规定的. (和制定 ECMAScript 标准的大佬们不是一伙人).
前面学的 JS 基础语法主要学的是 ECMAScript,这让我们建立基本的编程思维. 相当于练武需要先扎马步,但是真正来写一个更加复杂的有交互式的页面,还需要 WebAPI 的支持,相当于各种招式。下面我们重点讲解的是DOM API。
2. 什么是API?
API 是一个更广义的概念,而 WebAPI 是一个更具体的概念,特指 DOM
+ BOM
,所谓的 API 本质上就是一些现成的函数/对象
,让程序猿拿来就用,方便开发。
相当于一个工具箱,只不过程序猿用的工具箱数目繁多,功能复杂
💕 API参考文档
https://developer.mozilla.org/zh-CN/docs/Web/API
二、DOM基本概念
💕 什么是DOM?
DOM 全称为 Document Object Model
W3C 标准给我们提供了一系列的函数, 让我们可以操作:
- 网页内容
- 网页结构
- 网页样式
💕 DOM树
一个页面的结构是一个树形结构, 称为 DOM 树。
树形结构在数据结构阶段我们已经学过了,可以简单理解成类似于 “家谱” 这种结构,页面结构形如:
DOM 树结构形如:
重要概念:
- 文档: 一个页面就是一个 文档, 使用
document
表示. - 元素: 页面中所有的标签都称为 元素. 使用
element
表示. - 节点: 网页中所有的内容都可以称为 节点(标签节点,注释节点,文本节点,属性节点等),使用
node
表示。
这些文档等概念在 JS 代码中就对应一个个的对象,所以才叫 “文档对象模型
”。
三、获取元素
这部分工作类似于 CSS 选择器
的功能
💕 querySelector
这个是 HTML5 新增的, IE9 及以上版本才能使用
前面的几种方式获取元素的时候都比较麻烦,而使用 querySelector
能够完全复用前面学过的 CSS 选择器知识,达到更快捷更精准的方式获取到元素对象。
var element = document.querySelector(selectors);
selectors
包含一个或多个要匹配的选择器的 DOM字符串 DOMString 。 该字符串必须是有效的CSS选择器字符串;如果不是,则引发 SYNTAX_ERR 异常- 表示文档中与指定的一组CSS选择器匹配的第一个元素的 html元素
Element
对象. - 如果您需要与指定选择器匹配的所有元素的列表,则应该使用
querySelectorAll()
- 可以在任何元素上调用,不仅仅是
document
。 调用这个方法的元素将作为本次查找的根元素
正因为参数是选择器, 所以一定要通过特殊符号指定是哪种选择器:
<script> console.log(document.querySelector('.box1')) console.log(document.querySelector('h3').querySelector('span').querySelector('input'))</script>
使用document会选择到整个页面。
💕 querySelectorAll
console.log(document.querySelectorAll('div'))
三、事件初识
事件
是发生在你正在编程的系统中的事情——当事件发生时,系统产生(或“触发”)某种信号,并提供一种机制,当事件发生时,可以自动采取某种行动(即运行一些代码)。事件是在浏览器窗口内触发的,并倾向于附加到驻留在其中的特定项目。这可能是一个单一的元素,一组元素,当前标签中加载的 HTML 文档,或整个浏览器窗口。有许多不同类型的事件可以发生。
💕 基本概念
JS 要构建动态页面, 就需要感知到用户的行为。
用户对于页面的一些操作(点击, 选择, 修改等) 操作都会在浏览器中产生一个个事件, 被 JS 获取到, 从而进行更复杂的交互操作。
浏览器就是一个哨兵, 在侦查敌情(用户行为). 一旦用户有反应(触发具体动作), 哨兵就会点燃烽火台的狼烟(事件), 后方就可以根据狼烟来决定下一步的对敌策略。
💕 事件三要素
- 事件源: 哪个元素触发的
- 事件类型: 是点击, 选中, 还是修改?
- 事件处理程序: 进一步如何处理. 往往是一个回调函数
1. 点击事件
下面我们来看一个简单的点击事件:
<script> // 事件源 let button = document.querySelector('input') // 1. 绑定事件类型(点击事件) 2. 函数设定了事件处理程序 button.onclick = function() { alert("hello, 你好吖") }script>
2. 键盘事件
onkeydown
事件:当用户按下键盘上的任何键
时触发,包括字符键、功能键和控制键。onkeypress
事件:当用户按下字符键
(例如字母、数字、符号键)时触发。onkeyup
事件:当用户释放键盘上的键时触发,无论是字符键、功能键还是控制键。
💕 onkeydown
事件
示例一:
<input type="text"><script> // 事件源 let input = document.querySelector('input') input.onkeydown = function() { console.log("键盘正在按下") }script>
当我们按键盘的过程中会有如下效果:
event
—> 事件处理程序通常会接收一个事件对象(通常命名为 event
或 e
),该对象包含与触发事件相关的信息和属性。事件对象提供了有关事件的详细信息,使开发人员能够对事件进行更精细的控制和响应。
String.fromCharCode()
是 JavaScript 中的一个方法,用于将一个或多个字符编码的 Unicode 值转换为相应的字符串。这个方法可以接受一个或多个 Unicode 值作为参数,并返回由这些 Unicode 值构成的字符串。
示例二:
<input type="text"><script> let input = document.querySelector('input') input.onkeydown = function(event) { let a = event.keyCode let b = String.fromCharCode(a) console.log(b) }script>
💕 onkeypress
事件
当我们使用onkeydown
事件时,发现无论按下的字母是大写还是小写,他输出在控制台上时都是大写。使用onkeypress可以有效解决这个问题。
<input type="text"><script> let input = document.querySelector('input') input.onkeypress = function(event) { let a = event.keyCode let b = String.fromCharCode(a) console.log(b) }script>
💕 onkeyup
事件
onkeyup
事件是在键盘按下去弹起来的时候才会触发的事件。
<input type="text" onkeyup="myOnkeyUp()"><script> let input = document.querySelector('input') input.onkeypress = function(event) { let a = event.keyCode let b = String.fromCharCode(a) console.log(b) } function myOnkeyUp() { console.log("按键被抬起") }script>
但是有时候我们输入的是特殊键的时候,将不会打印在控制台上,比如说:shift
键、alt
键等。
可以看到控制台并没有打印。那是因为这些键需要特殊处理:
例如:
<input type="text" onkeyup="myOnkeyUp()"><script> let input = document.querySelector('input') input.onkeydown = function(event) { // 如果按键按下的是shift此时弹出一个弹窗,提示shift被按下 if(event.shiftKey) { alert("shift键被按下") } if(event.altKey) { alert("alt键被按下") } } function myOnkeyUp() { console.log("按键被抬起") }script>
四、操作元素
1. 获取/修改元素内容
💕 innerText
Element.innerText
属性表示一个节点及其后代的“渲染
”文本内容
<body> <div> <span>hello worldspan> <span>hello worldspan> div>body><script> var div = document.querySelector('div') // 读取 div 内部内容 console.log(div.innerText) // 修改 div 内部内容, 界面上就会同步修改 div.innerText = 'hello js hello js'script>
💕 innerHTML
Element.innerHTML
属性设置或获取HTML语法表示的元素的后代
<body> <span>这是一个span标签span>body><script> // 获取元素内容 let span = document.querySelector('span') console.log(span.innerHTML) // 修改 span.innerHTML = "我在修改元素内容" // 修改页面结构 span.innerHTML = "这是h3标签
"script>
2. 获取/修改元素属性
可以通过 Element
对象的属性来直接修改, 就能影响到页面显示效果。
<body> <img src="../百度logo图标.png" alt="图片加载失败" title="这是一个提示图片" width="100px" height="100px">body><script> let img = document.querySelector('img') console.dir(img) img.title = "这是已经修改完毕的title" img.onclick = function() { alert("你已经点击了这个图片") }script>
3. 获取/修改表单元素属性
表单
(主要是指 input 标签)的以下属性都可以通过 DOM
来修改:
- value: input 的值.
- disabled: 禁用
- checked: 复选框会使用
- selected: 下拉框会使用
- type: input 的类型(文本, 密码, 按钮, 文件等)
💕 实现播放按钮
<body> <input class="btn" type="button" value="播放" onclick="Onclick()">body><script> let btn = document.querySelector('.btn') // 当按钮的 value 变成 播放时, 此时将value按钮变成暂停。否则的话变成播放 function Onclick() { if(btn.value == '播放') btn.value = '暂停' else btn.value = '播放' }script>
💕 计数器实现:点击计数
使用一个输入框输入初始值(整数). 每次点击按钮, 值 + 1或者 值 -1
<body> <input class="input" type="text" value="0"> <input class="Add" type="button" value="+1" onclick="Add()"> <input class="Min" type="button" value="-1" onclick="Min()">body><script> function Add() { let input_element = document.querySelector('.input') input_element.value = parseInt(input_element.value) + 1 } function Min() { let input_element = document.querySelector('.input') input_element.value = parseInt(input_element.value) - 1 }script>
💕 复选框的选中效果
代码示例:全选/取消全选按钮
- 点击全选按钮,则选中所有选项
- 只要某个选项取消,则自动取消全选按钮的勾选状态
<body> <input class="all" type="checkbox" onclick="SelectAll()">选中全部<br> <input class="select" type="checkbox">貂蝉<br> <input class="select" type="checkbox">小乔<br> <input class="select" type="checkbox">安琪拉<br> <input class="select" type="checkbox">妲己<br>body><script> let all = document.querySelector('.all') let select = document.querySelectorAll('.select') // 当选中 “全部选中” 按钮时, 其他所有选项都将被选中 function SelectAll() { for(i = 0; i < select.length; i++){ select[i].checked = all.checked } } // 当其他选项中有任意一个选项没有被选中时, “全部选中”选项也不被勾选 for(i = 0; i < select.length; i++){ select[i].onclick = function() { all.checked = IsSelectAll(select) } } function IsSelectAll(select) { for(i = 0; i < select.length; i++){ if(select[i].checked == false) return false } return true }script>
4. 获取/修改样式属性
💕 行内样式操作
“行内样式”, 通过 style 直接在标签上指定的样式。优先级很高,适用于改的样式少的情况。
示例:
点击文字则放大字体
<body> <div style="font-size: 10px;" onclick="changeSize()">哈哈哈div>body><script> function changeSize() { let element = document.querySelector('div') console.log(element.style) let size = parseInt(element.style.fontSize) + 10 // element.style.cssText = "font-size:" + size + "px" element.style.fontSize = size + "px" }script>
💕 类名样式操作
修改元素的 CSS 类名,适用于要修改的样式很多的情况,由于 class 是 JS 的保留字, 所以名字叫做 className
示例:
开启夜间模式
- 点击页面切换到夜间模式(背景变成黑色)
- 再次点击恢复日间模式(背景变成白色)
代码实现:
<style> .light { background-color: aliceblue; color: black; width: 100%; height: 100%; } body, html { width: 100%; height: 100%; } .dark { background-color: black; color: white; width: 100%; height: 100%; }style><div class="light" onclick="changeStyle()">这是一段话<br>这是一段话<br>这是一段话<br>这是一段话<br>这是一段话<br>这是一段话<br>div><script> function changeStyle() { let element = document.querySelector('div') // 如果当前的样式为白天模式, 就切换成黑夜模式, 否则就将当前样式调整成白天模式 if(element.className == "light") { element.className = "dark" } else { element.className = "light" } }script>
五、操作节点
💕 什么是节点?
"节点
"通常指的是文档对象模型(DOM
)中的元素或对象。DOM是表示HTML和XML文档的树状结构,它将文档中的每个部分(如元素、属性、文本等)表示为对象,开发者可以使用JavaScript来访问、操作和修改这些对象,从而实现对文档的动态交互和修改。
1. 新增节点
分成两个步骤:
- 创建元素节点
- 把元素节点插入到 dom 树中
💕 创建元素节点
使用 createElement
方法来创建一个元素,options
参数暂不关注。
这是元素节点的创建方式,当然我们还可以创建别的:
createTextNode
创建文本节点createComment
创建注释节点createAttribute
创建属性节点
虽然创建出新的 div 了, 但是我们新创建的节点并没有加入到DOM 树中。
💕 插入节点到 dom 树中
- 使用
appendChild
将节点插入到指定节点的最后一个孩子之后
例如:
<div> <p class="p1">这是一个p标签1p> <p class="p2">这是一个p标签2p> <p class="p3">这是一个p标签3p> div>
插入到指定节点的最后一个孩子之后:
<script> let element = document.createElement('h3') element.innerHTML = "这是我创建的一个新节点" let div = document.querySelector('div') div.appendChild(element)script>
- 使用 insertBefore 将节点插入到指定节点之前
insertedNode
被插入节点(newNode)parentNode
新插入节点的父节点newNode
用于插入的节点newNode
将要插在referenceNode
这个节点之前
注意:
如果 referenceNode 为 null 则 newNode 将被插入到子节点的末尾,referenceNode 引用节点不是可选参数。
例如:
<div> <p class="p1">这是一个p标签1p> <p class="p2">这是一个p标签2p> <p class="p3">这是一个p标签3p>div>
<script> let div = document.querySelector('div') let new_node = document.createElement('p') new_node.innerHTML = "这是一个新p标签" div.insertBefore(new_node, document.querySelector('.p1'))script>
如果我们将insertBefore
中的第一个参数referenceNode设置为空时,新增的元素会被插在子节点的末尾。
div.insertBefore(new_node, null)
注意:
- 如果针对一个节点插入两次, 则只有最后一次生效(相当于把元素移动了)
- 一旦一个节点插入完毕, 再针对刚刚的节点对象进行修改, 能够同步影响到 DOM 树中的内容
2. 删除节点
使用 removeChild
删除子节点
- child 为待删除节点
- element 为 child 的父节点
- 返回值为该被删除节点
- 被删除节点只是从 dom 树被删除了, 但是仍然在内存中, 可以随时加入到 dom 树的其他位
置.- 如果上例中的 child节点 不是 element 节点的子节点,则该方法会抛出异常
删掉上面的p2标签:
<script> let div = document.querySelector('div') div.removeChild(document.querySelector('.p2'))script>
六、实战案例
1. 猜数字
💕 预期效果:
💕 代码实现:
DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Documenttitle> <style> .false { color: red; } .true { color: green; } style>head><body> <input class="reset_button" type="button" value="重新开始一局游戏" onclick="reSet()"><br> 请输入要猜的数字: <input class="to_guess_num" type="text" value="0"><input type="button" value="猜" onclick="Guess()"><br> 已经猜的次数: <span class="has_guess_num">0span><br> 结果: <span class="result">span>body><script> // 输入的数字 let to_guess_num_element = document.querySelector('.to_guess_num') console.dir(to_guess_num_element) // 已经猜的次数 let has_guess_num_element = document.querySelector('.has_guess_num') console.dir(has_guess_num_element) // 猜测的结果 let result_element = document.querySelector('.result') console.dir(result_element) function reSet() { to_guess_num_element.value = 0 has_guess_num_element.innerHTML = 0 result_element.innerHTML = "" } // 生成随机数作为我们要猜的数字 let num = Math.floor(Math.random()*100) + 1 console.log(num) function Guess() { has_guess_num_element.innerHTML = parseInt(has_guess_num_element.innerHTML) + 1 if(parseInt(to_guess_num_element.value) < num){ result_element.innerHTML = "猜小了" result_element.className = false } else if(parseInt(to_guess_num_element.value) > num) { result_element.innerHTML = "猜大了" result_element.className = false } else { result_element.innerHTML = "猜中了" result_element.className = true } }script>html>
2. 表白墙
💕 预期效果:
💕 代码实现:
DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Documenttitle> <style> * { margin: 0px; padding: 0px; } .container { width: 400px; margin: 0 auto; } h1 { text-align: center; margin-bottom: 40px; margin-top: 20px; } p { text-align: center; color: gray; line-height: 63px; } .div1 { display: flex; justify-content: center; align-items: center; } .divContent { display: flex; justify-content: center; align-items: center; margin-top: 20px; color: pink; } .edit { margin-bottom: 20px; width: 200px; height: 30px; } span { width: 50px; margin-bottom: 20px; } .submit { background-color: rgb(255, 157, 0); color: white; width: 260px; height: 30px; border: none; border-radius: 5px; } .submit:active{ background-color: gray; } style>head><body> <div class="container"> <h1>表白墙h1> <p>输入相关信息, 点击提交数据将会展示在表格中p> <div class="div1"> <span>谁: span><input type="text" class="edit"> div> <div class="div1"> <span>对谁: span><input type="text" class="edit"> div> <div class="div1"> <span>说: span><input type="text" class="edit"> div> <div class="div1"> <input type="button" value="提交" class="submit" onclick="Submit()"> div> div>body><script> function Submit() { let edits = document.querySelectorAll('.edit') console.dir(edits) let from = edits[0].value let to = edits[1].value let message = edits[2].value if(from == '' || to == '' || message == '') return console.log(from + " " + to + " " + message) let div = document.createElement('div') div.className = "divContent" div.innerHTML = from + "对" + to + "说: " + message console.log(div) let container = document.querySelector('.container') container.appendChild(div) }script>html>
3. 任务清单
💕 预期效果:
💕 代码实现:
DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Documenttitle> <style> * { margin: 0px; padding: 0px; box-sizing: border-box; } .nav { width: 800px; height: 100px; margin: 0 auto; display: flex; align-items: center; } .nav input { width: 600px; height: 60px; border-radius: 5px; } .nav button { width: 200px; height: 60px; background-color: orange; color: white; font-size: 20px; border: orange; border-radius: 5px; } .nav button:active { background-color: grey; } .container { width: 800px; display: flex; margin: 0px auto; } h3 { background-color: gray; color: white; text-align: center; width: 400px; height: 60px; padding-top: 15px; } .todo, .done { width: 50%; height: 100%; } .row { width: 400px; display: flex; align-items: center; } span { width: 200px; font-size: 20px; margin-left: 5px; } .row button { width: 90px; height: 40px; font-size: 20px; margin-top: 10px; } style>head><body> <div class="nav"> <input type="text"><button onclick="newJob()">新建任务button> div> <div class="container"> <div class="todo"> <h3>未完成h3> <div class="row"> <input type="checkbox" name="" id=""> <span>吃饭span><button>删除button> div> div> <div class="done"> <h3>已完成h3> div> div>body><script> function newJob() { // 获取到input输入框按钮 let input = document.querySelector('.nav input') // 获取到输入的信息 let input_info = input.value if(input_info == '') { return } console.log(input_info) // 获取到todo这个div let todo = document.querySelector('.todo') // 创建一个div let div = document.createElement('div') // 创建一个checkbox let checkbox = document.createElement('input') checkbox.type = 'checkbox' // 创建一个span(文本内容是刚才输入的信息对应的文本) let span = document.createElement('span') span.innerHTML = input_info console.log(checkbox) console.log(span) // 创建一个删除button let button = document.createElement('button') button.innerHTML = "删除" div.appendChild(checkbox) div.appendChild(span) div.appendChild(button) console.log(div) // 更新样式 div.className = 'row' // // 将div插入到todo这个div中 todo.appendChild(div) let delete_buttons = document.querySelectorAll('.row button') console.log(delete_buttons) for(i = 0; i < delete_buttons.length; i++) { delete_buttons[i].onclick = function() { let parent = this.parentNode; console.log(parent) let grand_parent = parent.parentNode console.log(grand_parent) grand_parent.removeChild(parent) } } let checkbox_buttons = document.querySelectorAll('.row input') // 给每一个复选框绑定点击事件 for(i = 0; i < checkbox_buttons.length; i++) { checkbox_buttons[i].onclick = function() { // 将节点插入到对应的div中 // row代表的插入的节点 let row = this.parentNode; // target代表的是将row插入到那个div中 // 如果复选框已经被选中,那么target就是已完成对应的这个div // 否则target就是未完成对应的div let target; console.log(this.checked) if(this.checked) { target = document.querySelector('.done') } else { target = document.querySelector('.todo') } target.appendChild(row) } }}script>html>
来源地址:https://blog.csdn.net/m0_67595314/article/details/132776059