目标:
能说出WebApi 与 JavaScript 的关联
能说出什么是API
能说出什么是WebApi
JS 基础阶段:
Web APIs 阶段
js 学习基础语法为后面作铺垫,WebAPIs 是JS 的应用,大量使用JS基础语法做交互效果
api是一些预先定义的函数,目的是提供应用程序与开发人员给予某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
简单理解:api是给程序员提供的一种工具,以便能更轻松的实现想要完成的功能。
webapi 是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)。
MDN详细API:https://developer.mozilla.org/zh-CN/docs/Web/API
获取页面中的元素可以使用以下几种方式:
- 根据 ID 获取
- 根据标签名获取
- 通过HTML5新增的方法获取
- 特殊元素获取
getElementById()
<body>
<div id="time">2021-09-19</div>
<script>
//1. 因为文档页面从上到下加载,所以要先有标签,所以script要写到下面
//2. 参数 id 大小写敏感的字符串
//3. 返回的是一个元素对象
var timer = document.getElementById('time');
console.log(timer);
console.log(typeof timer);
//4. console.dir 打印我们返回的元素对象 更好的查看里面的属性和方法
console.dir(timer);
</script>
</body>
getElementsByTagName() # 返回带有指定标签名的对象的集合
<body>
<ul>
<li>知否知否</li>
<li>知否知否</li>
<li>知否知否</li>
<li>知否知否</li>
</ul>
<ol>
<li>知否知否</li>
<li>知否知否</li>
<li>知否知否</li>
<li>知否知否</li>
</ol>
<script>
// 1. 返回的是 获取过来元素对象的集合,以伪数组的形式存储的
var lis = document.getElementsByTagName('li');
console.log(lis);
console.log(lis[0]);
// 2. 依次打印元素对象,采用遍历的方式
for (let i = 0; i < lis.length; i++) {
console.log(lis[i]);
}
// 3. 如果页面中只有一个li,返回的还是伪数组形式
// 4. 如果页面中没有元素,返回的还是伪数组形式
// 5. element.getElementsByTagName()
var ol = document.getElementsByTagName('ol'); //[ol]
console.log(ol[0].getElementsByTagName('li'));
</script>
</body>
- document.getElementByClassName(‘类名’); //根据类名返回元素对象的集合
- document.querySelector(‘选择器’); //根据指定选择器返回第一个元素对象
- document.querySelectorAll(‘选择器’); //根据指定选择器返回所有元素对象
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
// 1. getElementByClassName() 根据类名获取某些元素集合
var boxs = document.getElementsByClassName('box');
console.log(boxs);
// 2. querySelector() 返回指定选择器的第一个元素对象
var firstBox = document.querySelector('.box');
console.log(firstBox);
// 3. querySelectorAll() 返回指定选择器的所有元素对象
var allBox = document.querySelectorAll('.box');
console.log(allBox);
</script>
</body>
获取body元素:
document.body;
获取html元素:
document.documentElement;
<body>
<script>
//1. 获取body元素
var bodyEle = document.body;
console.log(bodyEle);
console.dir(bodyEle);
//2. 获取html元素
var htmlEle = document.documentElement;
console.log(htmlEle);
</script>
</body>
JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。
简单理解: 触发— 响应机制。
网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个
事件,然后去执行某些操作。
<body>
<button id="btn">唐伯虎</button>
<script>
//点击一个按钮,弹出对话框
//1.事件是由三部分组成:事件源,事件类型,事件处理程序。我们也称之为事件的三要素
// (1)事件源:时间被触发的对象 谁 按钮
var btn = document.getElementById('btn');
// (2)事件类型 如何触发 什么事件 如鼠标点击(onclick)
// (3)事件处理程序 通过一个函数赋值的方式完成
btn.onclick = function() {
alert('点秋香')
}
</script>
</body>
<body>
<div>123</div>
<script>
//执行事件的步骤
//点击div ,控制台输出:我被选中了
//1. 获取事件源
var div = document.querySelector('div');
//2. 绑定事件 注册事件
// div.onclick
//2. 添加事件处理程序
div.onclick = function() {
console.log('我被选中了!');
}
</script>
</body>
JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容 、属性等。注意以下都是属性
element.innerText
从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉
element.innerHTML
起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
<body>
<button>显示当前系统时间</button>
<div>某个时间</div>
<script>
//当我们点击了按钮,div里面的文字会发生变化
//1. 获取元素
var btn = document.querySelector('button');
var div = document.querySelector('div');
//2. 注册事件
btn.onclick = function() {
div.innerText = new Date();
}
</script>
</body>
innerText 与 innerHTML 的区别:
<body>
<div></div>
<div></div>
<p>我是文字
<span>123</span>
</p>
<script>
// innerText与innerHTML的区别
// 1. innerText 不识别html标签 非标准
var div = document.querySelectorAll('div');
div[0].innerText = '今天是:2021';
// 2. innerHTML W3C标准
div[1].innerHTML = '今天是:2021';
//这两个属性是可读写的,可以获取元素里面的内容
var p = document.querySelector('p');
console.log(p.innerText);
console.log(p.innerHTML);
</script>
</body>
修改图片 src
<body>
<button id="ldh">刘</button>
<button id=zxy>张</button>
<img src="https://pics5.baidu.com/feed/5366d0160924ab1828d302891e29f9c879890b9b.jpeg?token=23927fab33a65e66546edc273084fce3&s=80108F7A58F30686582C69F703005063" alt="" srcset="" width="200px" height="200px">
<script>
//修改元素 src
// 1.获取元素
var ldh = document.getElementById('ldh');
var zxy = document.getElementById('zxy');
var img = document.querySelector('img');
// 2.注册事件
zxy.onclick = function() {
img.src = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdingyue.nosdn.127.net%2F3WKmSi9G2oCkRdfU004xJEtTbc%3DPbkZFzLgi08W%3DAr0CR1499226607542.jpg&refer=http%3A%2F%2Fdingyue.nosdn.127.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1634865888&t=b65eb0551c13b0ddf42e8de05069b1c2';
};
ldh.onclick = function() {
img.src = 'https://pics5.baidu.com/feed/5366d0160924ab1828d302891e29f9c879890b9b.jpeg?token=23927fab33a65e66546edc273084fce3&s=80108F7A58F30686582C69F703005063';
};
</script>
</body>
<body>
<div>上午好</div>
<script>
// 根据系统不同时间来判断,所以需要用到日期内置对象
// 利用多分支语句来设置不同的图片
// 需要一个图片,并且根据时间修改图片,就需要用到操作元素src属性
// 需要一个div元素,显示不同问候语,修改元素内容即可
// 1.获取元素
var div = document.querySelector('div');
// 2.获取当前的小时数
var date = new Date();
var h = date.getHours();
// 3.判断
if (h < 12) {
div.innerHTML = '上午好';
} else if (h < 18) {
div.innerHTML = '下午好';
} else {
div.innerHTML = '晚上好';
}
</script>
</body>
利用 DOM 可以操作如下表单元素的属性:
type、value、checked、selected、disabled
<body>
<button>按钮</button>
<input type="text" value="输入内容">
<script>
// 1.获取元素
var btn = document.querySelector('button');
var input = document.querySelector('input');
// 2.注册事件,处理程序
btn.onclick = function() {
//表单里的值 文字内容是通过 value 来修改的
input.value = '被点击了!';
//如果想要某个表单被禁用 不能再点击 disabled
// btn.disabled = true;
// this 指向的是事件函数的调用者 btn
this.disabled=true;
}
</script>
</body>
仿京东显示密码案例:
<body>
<div class="box">
<label for="">密</label>
<input type="password" name="" id="">
</div>
<script>
//1. 获取元素
var label = document.querySelector('label');
var input = document.querySelector('input');
//2. 注册事件 绑定程序
var flag = 0;
label.onclick = function() {
if (flag == 0) {
input.type = 'text';
label.innerHTML = '明';
flag = 1;
} else {
input.type = 'password';
label.innerHTML = '密';
flag = 0;
}
}
</script>
</body>
算法:利用一个flag变量,来判断flag的值,如果是1 就切换为文本框,flag 设置为0,如果是0 就切换为密码框,flag设置为1 。
我们可以通过 JS 修改元素的大小、颜色、位置等样式。
- element.style 行内样式操作
- element.className 类名样式操作
注意:
1.JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor。
2.JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高。
<body>
<div></div>
<script>
// 1.获取元素
var div = document.querySelector('div');
// 2.注册事件 处理程序
div.onclick = function() {
// div.style 里面的属性采用的是驼峰命名法
this.style.backgroundColor = 'purple';
this.style.width = '250px';
}
</script>
</body>
淘宝关闭二维码案例:
核心思路: 利用样式的显示和隐藏完成, display:none 隐藏元素 display:block 显示元素
点击按钮,就让这个二维码盒子隐藏起来即可
<body>
<div>
<span>关</span>
</div>
<script>
//1.获取元素
var btn = document.querySelector('span');
var div = document.querySelector('div');
//2. 绑定事件
btn.onclick = function() {
div.style.display = 'none';
}
</script>
</body>
隐藏文本框内容案例:
<body>
<input type="text" value="手机">
<script>
//1.获取元素
var text = document.querySelector('input');
//2.注册事件 获得焦点 onfocus 失去焦点 onblur
text.onfocus = function() {
if (this.value === '手机') {
this.value = '';
}
};
text.onblur = function() {
if (this.value === '') {
this.value = '手机';
}
}
</script>
</body>
操作类名方式更改元素样式:
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
.change {
background-color: purple;
color: red;
font-size: 25px;
margin-top: 30px;
}
</style>
<body>
<div>文本</div>
<script>
// 1.获取元素
var div = document.querySelector('div');
div.onclick = function() {
// 将当前元素的类名改为了 change
this.className = 'change';
}
</script>
</body>
总结:操作元素是 DOM 核心内容
如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法:
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
//1.获取都有按钮元素
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
// 1.先将所有的按钮背景颜色去除掉
for (let i = 0; i < btns.length; i++) {
btns[i].style.backgroundColor = '';
}
// 2.然后才让当前的元素背景颜射为pink
this.style.backgroundColor = 'pink';
}
}
</script>
</body>
区别:
- element.属性 获取内置属性值(元素本身自带的属性)
- element.getAttribute(‘属性’); 主要获得自定义的属性 (标准) 我们程序员自定义的属性
<body>
<div id="demo" index='1'></div>
<script>
var div = document.querySelector('div');
// 1.获取元素的属性值
// (1) element.属性
console.log(div.id);
console.log(div.index);// undefined
// (2) element.getAttribute('属性')
console.log(div.getAttribute('id'));
console.log(div.getAttribute('index'));
</script>
</body>
区别:
- element.属性 设置内置属性值
- element.setAttribute(‘属性’,‘值’); 主要设置自定义的属性 (标准)
自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性获取是通过getAttribute(‘属性’) 获取。
但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
H5规定自定义属性 data- 开头做为属性名并且赋值。
比如
或者使用 JS 设置 element.setAttribute(‘data-index’, 2)
1. 兼容性获取 element.getAttribute(‘data-index’);
2. H5新增 element.dataset.index 或者 element.dataset[‘index’] ie 11才开始支持
获取元素通常使用两种方式:
- document.getElementById()
- document.getElementsByTagName()
- document.querySelector 等
- 逻辑性不强、繁琐
- 利用父子兄节点关系获取元素
- 逻辑性强, 但是兼容性稍差
这两种方式都可以获取元素节点,我们后面都会使用,但是节点操作更简单。
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。
HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个
基本属性。
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
父级节点
node.parentNode
<body>
<div class="box">
<span class="erweima"></span>
</div>
<script>
// 1. 父节点 parentNode
var erweima = document.querySelector('.erweima');
// 得到的是离元素最近的父节点(亲爸爸),如果找不到就返回为 null
console.log(erweima.parentNode);
</script>
</body>
子节点(标准)
parentNode.childNodes
返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。
如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes
子节点(非标准)
parentNode.children
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回 (这个是我们重点掌握的)。
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
// 2. 子节点
var ul = document.querySelector('ul');
// childNodes 获取的子节点包含 元素节点 文本节点等等
console.log(ul.childNodes);
// parentNode.children 只返回子元素节点
console.log(ul.children);
</script>
</body>
parentNode.firstChild
firstChild 返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。
parentNode.lastChild
lastChild 返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点。
parentNode.firstElementChild
firstElementChild 返回第一个子元素节点,找不到则返回null。
parentNode.lastElementChild
lastElementChild 返回最后一个子元素节点,找不到则返回null。
注意:后两个方法有兼容性问题,IE9 以上才支持。
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var ul = document.querySelector('ul');
// 1. firstChild 第一个子节点 文本节点与元素节点
console.log(ul.firstChild);
// 2. firstChild 第一个子节点 文本节点与元素节点
console.log(ul.lastChild);
// 3. firstElementChild 第一个元素节点
console.log(ul.firstElementChild);
// 4. lastElementChild 最后一个元素节点
console.log(ul.lastElementChild);
</script>
</body>
实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而firstElementChild 和 lastElementChild 又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?
解决方案:
- 如果想要第一个子元素节点,可以使用 parentNode.chilren[0]
- 如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1]
node.nextSibling
nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
node.previousSibling
previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
node.nextElementSibling
nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回null。
node.previousElementSibling
previousElementSibling 返回当前元素上一个兄弟节点,找不到则返回null。
注意:这两个方法有兼容性问题, IE9 以上才支持。
document.createElement('tagName')
document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为 动态创建元素节点 。
node.appendChild(child)
node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素。
node.insertBefore(child, 指定元素)
node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素。
<body>
<ul>
<li>123</li>
</ul>
<script>
//1. 创建节点元素节点
var li = document.createElement('li');
//2. 添加节点 node.appendChild(child) 在后面追加元素
var ul = document.querySelector('ul');
ul.appendChild(li);
//3. 添加节点 node.insertBefore(child,指定元素);
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
</script>
</body>
添加留言板案例:
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul></ul>
<script>
//1. 获取元素
var text = document.querySelector('textarea');
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
//2. 注册事件
btn.onclick = function() {
if (text.value != '') {
// 创建元素
var li = document.createElement('li');
li.innerHTML = text.value;
// 添加元素
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0])
text.value = '';
} else {
alert('没有输入内容!');
return false;
}
}
</script>
</body>
node.removeChild(child)
node.removeChild() 方法从 DOM 中删除一个子节点,返回删除的节点。
删除留言板内容案例:
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul></ul>
<script>
//1. 获取元素
var text = document.querySelector('textarea');
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
//2. 注册事件
btn.onclick = function() {
if (text.value != '') {
// 创建元素
var li = document.createElement('li');
li.innerHTML = text.value + "删除";
// 添加元素
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0])
text.value = '';
// 3. 删除元素,删除的是当前链接的li
var as = document.querySelectorAll('a');
for (let i = 0; i < as.length; i++) {
as[i].onclick = function() {
//这里要注意
ul.removeChild(this.parentNode);
}
}
} else {
alert('没有输入内容!');
return false;
}
}
</script>
</body>
node.cloneNode()
node.cloneNode() 方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点。
注意:
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
// 1. node.cloneNode(true); 括号里true为深拷贝,否则为浅拷贝,浅拷贝不拷贝内容
var lili = ul.children[0].cloneNode(true);
ul.appendChild(lili);
</script>
</body>
区别:
- document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
- innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
- innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
- createElement() 创建多个元素效率稍低一点点,但是结构更清晰
总结:不同浏览器下,innerHTML(数组形式) 效率要比 creatElement 高
文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。
主要获取查询dom的元素:
声明:
本文是本人通过学习黑马相关课程所做的总结,文章部分内容来自黑马提供的 ppt 中截取。