【Web前端】
JavaScript(WebAPI)
WebAPI背景知识
什么是WebAPI
JS可以分成三个部分
- ECMAScript:基础语法部分
- DOM(Document Object Model):操作页面结构
- BOM(Broswer Object Model):操作浏览器
WebAPI就包含了DOM+BOM
这个是W3C组织规定的(和制定ECMAScript标准的大佬们不是一伙人)
什么是API
API是一个更广义的概念,而WebAPI是一个更具体的概念,特指DOM+BOM
所谓的API本质上就是一些现成的函数/对象,让程序员拿来就用,方便开发。
相当于一个工具箱,只不过程序员用的工具箱数目繁多,功能复杂。
DOM基本概念
什么是DOM
W3C标准给我们提供了一系列的函数,让我们可以操作:
- 网页内容
- 网页结构
- 网页样式
DOM树
一个页面的结构是一个树形结构,称为DOM树
树形结构在数据结构阶段会介绍,既可以简单理解成类似于“家谱”这种结构
页面结构形如:
重要概念:
- 文档:一个页面就是一个文档,使用document表示
- 元素:页面中所有的标签都可以称为元素,使用element表示
- 节点:网页中所有的内容都可以称为节点(标签节点、注释节点、文本节点、属性节点等)。使用node表示
这些文档等概念在JS代码中就对应一个个的对象, 所以才叫做“文档对象模型”。
获取元素
这部分工作类似于CSS选择器的功能
querySelector
let element = document.querySelector(selectors);
- selector包含一个或者多个要匹配的选择亲戚的DOM字符串。该字符串必须是有效的,CSS选择器字符串;如果不是,则印发SYN_ERR异常
- 表示文档中与指定的一组CSS选择器匹配的第一个元素的html元素Element对象
- 如果您需要与指定选择器匹配的所有元素的列表,则应该使用querySelectorAll()
- 可以在任何元素上调用,不仅仅是document。调用这个方法的元素将作为本次查找的根元素。
选择器
-
类选择器(.className)
-
ID选择器(.ID)
-
全局选择器(*)
-
关系选择器
子代关系选择器(article > p)
邻接兄弟(p+img)
通用兄弟(p~img)
符合关系选择器(ul > li[class=“a”]) -
伪类选择器(:hover :acitive)
-
属性选择器
具体使用可以参照下面代码:
querySelectorAll
使用querySelectorAll用法和上面类似
<div class="box">abc</div>
<div id="id">def</div>
<script>let elems = document.querySelectorAll('div');console.log(elems)
</script>
事件初始
基本概念
JS要构建动态页面,就需要感知到用户的行为
用户对于页面的一些操作(点击、选择、修改)操作都会在浏览器中产生一个个事件,被JS获取到,从而进行更复杂的交互操作
浏览器就是一个哨兵,在侦查敌情·(用户行为),一旦用户有反应(触发具体动作),哨兵就会点燃烽火 台的狼烟(时间),后方就可以根据狼烟来决定下一步的对敌策略。
事件三要素
HTML DOM事件
- 事件源:哪个元素触发的
- 事件类型:是点击、选中还是修改?
- 时间处理程序:进一步如何处理,往往是一个回调函数
onclick事件
<button id="btn">点我一下</div><script>let btn = document.querySelector('#btn')btn.onclick=function(){alert("hello world");}</script>
- btn按钮就是事件源
- 点击就是事件类型
- function这个匿名函数就是事件处理程序
- 其中btn.onclick = function()这个操作就称为注册事件/绑定事件
注意:这个匿名函数相当于一个回调函数,这个函数不需要程序员主动来调用,而是交给浏览器,由浏览器自动在合适的时机(触发点击操作时)进行调用。
onkeydown事件
<input type="text"><script>//事件源let input = document.querySelector('input')input.onkeydown=function(event){console.log('键盘正在按下');let a = event.keyCode;let b = String.fromCharCode(a);console.log(b)}</script>
可以看到运行结果不能区分大小写,所以我们的onkeypress就是为了解决这个问题
onkeypress事件
<input type="text"><script>//事件源let input = document.querySelector('input')input.onkeypress=function(event){console.log('键盘正在按下');let a = event.keyCode;let b = String.fromCharCode(a);console.log(b)}</script>
onkeyup事件
<input type="text" onkeyup="myOnKeyUp()"><script>//事件源let input = document.querySelector('input')input.onkeypress=function(event){console.log('键盘正在按下');let a = event.keyCode;let b = String.fromCharCode(a);console.log(b)}function myOnKeyUp(){console.log('按键被抬起')}</script>
onkeydown
<input type="text"><script>//事件源let input = document.querySelector('input')input.onkeydown=function(event){if(event.shiftKey){console.log('shift按键被按下')}if(event.altKey){console.log('alt按键被按下')}}</script>
获取/修改表单元素属性
表单(主要是指input标签)的以下属性都可以通过DOM来修改
- value:input的值
- disable:禁用·
- checked:复选框会使用
- selected:下拉框会使用
- type:input的类型(文本、密码、按钮、文件等)
<input class="btn" type="button" value="播放" onclick="onClick()">
<script>let btn = document.querySelector('.btn')//判断按钮的值为播放,就变成暂停;暂停就变成播放function onClick(){if(btn.value == "播放"){btn.value = "暂停"}else{btn.value = "播放"}}
</script>
点击计数
<input class='input' type="text" value="0"><input class='add' type="button" value="+1" onclick="ADD()"><input class='sub' type="button" value="-1" onclick="SUB()"></body>
<script>let btn = document.querySelector('.input')let input = document.querySelector('.input')//判断按钮的值为播放,就变成暂停;暂停就变成播放function ADD(){let input=document.querySelector(".input")input.value=parseInt(input.value)+1}function SUB(){let input=document.querySelector(".input")input.value=parseInt(input.value)-1}
复选框的应用
<input class='all' type="checkbox" onclick='selectAll()'> 选中全部<br><input class='select' type="checkbox">选项1<br><input class='select' type="checkbox">选项2<br><input class='select' type="checkbox">选项3<br><input class='select' type="checkbox">选项4<br></body>
<script>// let btn = document.querySelector('.input')// let input = document.querySelector('.input')// //判断按钮的值为播放,就变成暂停;暂停就变成播放// function ADD(){// let input=document.querySelector(".input")// input.value=parseInt(input.value)+1// }// function SUB(){// let input=document.querySelector(".input")// input.value=parseInt(input.value)-1// }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>
获取/修改样式属性
CSS中指定元素的属性,都可以通过JS来修改
行内样式操作
element.style.[属性名]=[属性值];
element.style.cssText=[属性名+属性值]
“行内样式”,通过style直接在标签上制定的样式,优先级很高
适用与改的样式少的情况
类名样式操作
element.className=[css 类名]
点击文字就放大字体
这种方式修改只影响到特定样式,其他内联样式的值不变
<div style="font-size: 10px;">哈哈哈</div>
</body>
<script>let element=document.querySelector('div');element.onclick=function(){let size=parseInt(element.style.fontSize); size+=10;// element.style.fontSize =size +'px';element.style.cssText="font-size:"+size+'px'}
</script>
黑夜模式&&白天模式切换
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.light{background-color: white;color:black;width:100%;height:100%;}.dark{background-color: black;color:white;width:100%;height:100%;}*{width:100%;height:100%;}</style>
</head>
<body><div class="light" onclick="changeStyle()">这是一段话<br>这是一段话<br>这是一段话<br>这是一段话<br>这是一段话<br>这是一段话<br>这是一段话<br>这是一段话<br></div>
</body>
<script>function changeStyle(){let element=document.querySelector('div')if(element.className=='light'){element.className="dark"}else{element.className="light";}}
</script>
</html>
操作节点
新增节点
分成两个步骤
- 创建元素节点
- 把元素节点插入到dom树中
1.创建元素节点
使用createElement方法创建一个元素,option参数暂不关注
let element=document.createElement(tagName[,option]);
2.插入节点到dom树中
1)使用appendChild将节点插入到指定节点的最后一个孩子之后
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div><p>这是一个p标签</p><p>这是一个p标签</p><p>这是一个p标签</p><p>这是一个p标签</p></div>
</body>
<script>let element=document.createElement("h3")element.innerHTML="这是我们创建的一个新节点"let div=document.querySelector("div")div.appendChild(element)
</script>
</html>
运行结果:
2)使用InsertBefore将节点插入到指定节点之前
let insertNode=parentNode.insertBefore(newnode,referenceNode);
- insertNode 被插入节点(newNode)
- parentNode 被插入节点的父节点
- newNode 用于被插入的节点
- referenceNode newNode将要插在这个节点之前
如果referenceNode为null则newNode将被插入到子节点的末尾
注意1:如果针对一个节点插入两次,则只有最后一次生效(相当于把元素移动了)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div><p class="p1">这是一个p标签</p><p class="p2">这是一个p标签</p><p class="p3">这是一个p标签</p><p class="p4">这是一个p标签</p></div>
</body>
<script>let element=document.createElement("h3")element.innerHTML="这是我们创建的一个新节点"let div=document.querySelector("div")div.appendChild(element)let newNode=document.createElement('h3')newNode.innerHTML="这是我们创建的另一个新节点"div.insertBefore(newNode,document.querySelector('.p1'))div.insertBefore(newNode,document.querySelector('.p2'))div.insertBefore(newNode,document.querySelector('.p3'))div.insertBefore(newNode,document.querySelector('.p4'))
</script>
</html>
注意2:一旦一个节点插入完毕,在针对刚刚的节点对象进行修改,能够同步影响到DOM树中的内容
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div><p class="p1">这是一个p标签</p><p class="p2">这是一个p标签</p><p class="p3">这是一个p标签</p><p class="p4">这是一个p标签</p></div>
</body>
<script>let element=document.createElement("h3")element.innerHTML="这是我们创建的一个新节点"let div=document.querySelector("div")div.appendChild(element)let newNode=document.createElement('h3')newNode.innerHTML="这是我们创建的另一个新节点"div.insertBefore(newNode,document.querySelector('.p1'))div.insertBefore(newNode,document.querySelector('.p2'))div.insertBefore(newNode,document.querySelector('.p3'))div.insertBefore(newNode,document.querySelector('.p4'))// element.innerHTML="我在修改这个标签"
</script>
</html>
任务清单页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><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 0 0 5px;}.nav button{width:200px;height:60px;background-color: orange;color:white;font-size:20px;border:orange;border-radius: 0 5px 5px 0;}.nav button:active{background-color: grey;}.container{width:800px;display: flex;margin:0px auto;}h3{background-color: grey;color:white;text-align: center;width:400px;height:60px;padding-top:15px;}.row{width:400px;display:flex;align-items: center;}.row span{width:200px;font-size:20px;margin-left:5px;}.row button{width:50px;height:40px;font-size:20px;margin-top:10px;}.done{width:50%;height:100%;}span{width:100px;}</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="" i=""><span>吃饭</span><button>删除</button></div></div><div class="done"><h3>已完成</h3></div></div>
</body>
<script>function newJob(){//获取数据let input=document.querySelector('.nav input')let input_info=input.valueif(input_info==''){return}//获取todolet todo=document.querySelector('.todo')//创建一个divlet div=document.createElement('div')//创建一个checkboxlet checkbox=document.createElement('input')checkbox.type="checkbox"//创建一个span(文本内容是刚才输入的信息)let span=document.createElement('span')span.innerHTML=input_info//创建一个buttonlet button=document.createElement('button')button.innerHTML="删除"div.appendChild(checkbox)div.appendChild(span)div.appendChild(button)//更新样式div.className='row'//将div插入到todo这个div中todo.appendChild(div)let deleteButtons=document.querySelectorAll('.row button')for(i=0;i<deleteButtons.length;i++){deleteButtons[i].onclick=function(){let parent=this.parentNode;let grandParent=parent.parentNode;grandParent.removeChild(parent);}}let checkbox_buttons=document.querySelectorAll('.row input')//绑定点击事件for(i=0;i<checkbox_buttons.length;i++){let row=document.querySelector('.row')let done;checkbox_buttons[i].onclick=function(){if(this.checked==true){done=document.querySelector('.done')done.appendChild(row)}else{done=document.querySelector('.todo')}// console.log(typeof(row))}}}
</script>
</html>
效果: