导读
什么是API?
API(Application Programming Interface 应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
简单理解为:API是提供给程序员的一种工具,以便可以轻松实现想要完成的功能
JS与web API的关联
JavaScript基础学习ECMAScript基础语法为后面做铺垫,web API是JavaScript的应用,大量使用JavaScript基础语法做出交互效果
JavaScript的组成
web API是什么
- web API 是浏览器提供的一套操作浏览器功能和页面元素的API(BOM与DOM)
- 针对于浏览器常用的API,可以做出交互效果
- MDN详细的API查阅:https://developer.mozilla.org/zh-CN/docs/Web/API
- 鉴于数量众多,现阶段称其为web APIs
DOM简介
什么是DOM
文档对象模型(Document Object Model),是W3C组织推荐的处理可扩展标记语言(HTML或XML)的标准编程接口
W3C已经定义了一些列的DOM接口,通过这些DOM接口可以改变网页的内容、结构或样式
DOM树
- 文档:一个页面就是一个文档,DOM中使用document表示
- 元素:页面中的所有标签都是元素,DOM中用element表示
- 节点:网页中所有的内容都是节点(标签、属性、文本、注释等),DOM中用node表示
DOM把以上内容都看做是对象
获取元素
因为文档是从上往下加载,所以必须先有HTML标签,如果在HTML加载完毕之前执行JavaScript,可能会造成网页渲染错误
getElementById():根据ID获取元素
var timer = document.getElementById('time'); // 返回一个dom的element对象
console.log(timer);
console.log(typeof timer); // object
console.dir(timer); // 打印返回的元素对象,可查看里面的属性与方法
getElementsByTagName():根据标签名获取元素
var lis = document.getElementsByTagName('li'); // 返回元素对象的集合,并以伪数组的形成存储
console.log(lis);
console.log(lis[0]);
遍历方式
for (var i = 0; i < lis.length; i++) {
console.log(lis[i]);
}
获取父元素中的子元素
var ol = document.getElementsByTagName('ol');
console.log(ol[0].getElementsByTagName('li')); // 因为获取的父元素返回的是伪数组形式,所以必须制定一个元素对象
或者使用ID来获取父元素
var ol = document.getElementById('ol');
console.log(ol.getElementsByTagName('li'))
HTML5 新增的获取元素方法
getElementByClassName():根据类名获取元素
var boxs = document.getElementsByClassName('box');
console.log(boxs);
querySelector():返回指定选择器的第一个元素对象
var firstbox = document.querySelector('.box');
console.log(firstbox);
var nav = document.querySelector('#nav');
console.log(nav);
querySelectorAll():返回指定选择器的所有元素对象(同样返回伪数组)
var allBox = document.querySelectorAll('.box')
console.log(allBox);
获取HTML和body
获取body
var bodyEle = document.body;
console.log(bodyEle);
console.log(typeof bodyEle); // object
获取HTML
var htmlEle = document.documentElement;
console.log(htmlEle);
console.log(typeof htmlEle); // object
事件基础
事件三要素:事件源、事件对象、事件处理程序
- 事件源:事件被触发的对象
var btn = document.getElementById('btn');
事件类型:如何触发
事件处理程序:通过一个函数赋值的方式来完成
btn.onclick = function () {
alert('HelloWorld');
}
操作元素
修改元素内容
// 获取事件源:
var btn1 = document.querySelector('#btn1');
var div = document.querySelector('#show');
// 注册事件:
btn1.onclick = function () {
div.innerText = getTime();
}
function getTime() {
var day = new Date();
var h = day.getHours();
h = h < 10 ? '0' + h : h;
var m = day.getMinutes();
m = m < 10 ? '0' + m : m;
var s = day.getSeconds();
s = s < 10 ? '0' + s : s;
var time = `${h}:${m}:${s}`
return time;
}
当然也可以不添加事件直接调用函数:
var p = document.querySelector('p');
p.innerText = getTime(); // 刷新浏览器将自动显示时间
innerText 和 innerHTML的区别
- innerText 不识别HTML标签; innerText 会自动去除元素内的空格和换行
var div = document.querySelector('div');
div.innerText = '<strong> Hello! </strong> , how are you ?'
- innerHTML 可以识别HTML标签; innerHTML 会保留元素内的空格和换行
var div = document.querySelector('div');
div.innerHTML = '<strong> Hello! </strong> , how are you ?'
对于同一段代码而言,两种方式有本质上的区别
这两种属性都是可以读写的:
var p = document.querySelector('p');
console.log(p.innerText);
console.log(p.innerHTML);
不过相比之下,innerHTML是由W3C标准制定出来的,所以更推荐使用!
修改元素属性
// 修改 src 属性:
// 获取元素
var btn1 = document.querySelector('.btn1');
var btn2 = document.querySelector('.btn2');
var img = document.querySelector('img');
// 注册事件 处理程序
btn1.onclick = function(){
img.src = 'pic/Kana.jpg'; // 与修改元素内容不同,修改元素属性只需要用点表示法就行了
img.title = 'Kana';
}
btn2.onclick = function(){
img.src = 'pic/Megumin.jpg';
img.title = 'Megumin';
}
// 此外,经常改变的元素属性还有 href 连接,可自行尝试
修改表单属性
// 获取元素
var btn = document.querySelector('button');
var input = document.querySelector('input')
// 注册事件 处理程序
btn.onclick = function(){
// input.innerHTML = 'I am clicked!'
// 结果当然不能更改表单里的值,因为innerHTML仅仅适用于修改普通盒子里的内容,比如div
input.value = 'I am clicked!'; // 修改表单内的值,需使用value属性
// 按钮禁用
// btn.disabled = true;
this.disabled = true;
// this 指向事件函数的调用者,即btn
}
修改样式属性
// 获取元素
var div = document.querySelector('div');
// 注册事件 处理程序
div.onclick = function(){
// div.style 里的样式属性 需要采用驼峰命名法
this.style.backgroundColor = 'yellow';
this.style.width = '250px'
// JS修改style样式,新产生的是行内样式,CSS权重比价高,所以能覆盖掉内联样式表中的样式
}
// 点击按钮隐藏图片
var pic = document.querySelector('.box');
var close = document.querySelector('i');
close.onclick = function(){
pic.style.display = 'none';
}
使用className修改样式属性
html:
<body>
<button>change style</button>
<div class="box">
</div>
</body>
CSS:
<style>
.box {
width: 200px;
height: 200px;
margin: 60px auto;
background-image: url(pic/Kana.jpg);
background-size: contain;
background-repeat: no-repeat;
}
.change {
width: 200px;
height: 200px;
margin: 60px auto;
background-image: url(pic/Megumin.jpg);
background-size: contain;
background-repeat: no-repeat;
}
</style>
js:
// 类名样式操作
// element.style 行内样式操作适用于简单并且样式数量较少修改
// 对于样式修改较为复杂的元素,推荐使用 element.className (类名样式操作)进行修改
var btn = document.querySelector('button');
var box = document.querySelector('.box');
btn.onclick = function(){
// box.class = 'change'; 这样写是错误的
box.className = 'change';
}
// class因为是保留字,因此规定使用className来操作类名属性
// className 会直接更改元素的类名,并且覆盖掉原来的1类名
// 如果需要添加多个类名样式,可以这样做:
// element.className = 'class1 class2'
操作元素总结
排他算法
html:
<body>
<div class="box">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</body>
css:
<style>
.box {
margin: 100px auto;
width: 600px;
height: 100px;
display: flex;
justify-content: space-around;
}
.item {
width: 50px;
height: 50px;
background-color: turquoise;
}
</style>
js:
<script>
// 排他算法
var item = document.getElementsByClassName('item');
for (var i = 0; i < item.length; i++){ // 利用循环,为每一个元素添加事件
item[i].onclick = function(){ // 侦测到点击事件,就把所有元素都设置为蓝色,再把被点击的那个元素设为红色
for (var i = 0; i < item.length; i++){
item[i].style.backgroundColor = 'turquoise';
}
this.style.backgroundColor = 'red';
}
}
</script>
自定义属性
html:
<body>
<div id="demo" index='1' class="nav"></div>
</body>
获取元素属性值
element.属性
这种方法只能获取内置属性的值(元素本身自带属性,如id , class...)
console.log(div.id);
element.getAttribute('属性')
这种方法除了可以获取内置属性值以外,还可以获取自定义的属性值,比如上面的index
console.log(div.getAttribute('id'));
console.log(div.getAttribute('index'));
设置属性值
element.'属性' = '值'
div.id = 'test';
div.className = 'navs';
element.setAttribute('属性','值')
div.setAttribute('index',2);
div.setAttribute('class','footer'); // 注意这里是class而不是className
移除属性
element.removeAttribute('属性值')
div.removeAttribute('index');
自定义属性使用案例
再这个案例中,内容会随着tab栏的切换而更变
关键在于,每一个tab栏与内容是相对应的,利用自定义属性可以处理好这种一一对应的关系
以下是实现代码:
html:
<body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价(50000)</li>
<li>手机社区</li>
</ul>
</div>
<div class="tab_con">
<div class="item" style="display: block;">
商品介绍模块内容
</div>
<div class="item">
规格与包装模块内容
</div>
<div class="item">
售后保障模块内容
</div>
<div class="item">
商品评价(50000)模块内容
</div>
<div class="item">
手机社区模块内容
</div>
</div>
</div>
</body>
css:
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
.tab {
width: 978px;
margin: 100px auto;
}
.tab_list {
height: 39px;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab_list li {
float: left;
height: 39px;
line-height: 39px;
padding: 0 20px;
text-align: center;
cursor: pointer;
}
.tab_list .current {
background-color: #c81623;
color: #fff;
}
.item_info {
padding: 20px 0 0 20px;
}
.item {
display: none;
}
</style>
js:
<script>
// 仿京东商品tab栏切换
// 获取元素
var lis = document.querySelector('.tab_list').querySelectorAll('li');
var item = document.querySelector('.tab_con').querySelectorAll('.item');
// 为每个标签添加事件
for (var i = 0; i < lis.length; i++) {
lis[i].setAttribute('index', i); // 对标签栏设置自定义属性
lis[i].onclick = function () {
for (var i = 0; i < lis.length; i++) { // 排他算法
lis[i].className = '';
}
this.className = 'current';
// 更改对应模块内容
// console.log(this.getAttribute('index'));
for (var i = 0; i < item.length; i++) { // 排他算法
item[i].style.display = 'none';
}
item[this.getAttribute('index')].style.display = 'block';
}
}
</script>
H5当中的自定义属性
节点
为什么学习节点操作
节点概述
节点类型
父节点与子节点
先看html:
<body>
<div>我是div</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<div class="demo">
<div class="box">
<span class="erweima">×</span>
</div>
</div>
</body>
- 父节点 parentNode
var erweima = document.querySelector('.erweima');
console.log(erweima.parentNode);
// 得到的是离元素最近的父级节点,如果找不到父节点则返回null
- 子节点 childNodes 包含所有的子节点(元素节点、文本节点...)
var ul = document.querySelector('ul');
console.log(ul.childNodes); // NodeList(9) [text, li, text, li, text, li, text, li, text]
console.log(ul.childNodes[0].nodeType); // 3,表示此节点为文本节点(换行)
console.log(ul.childNodes[1].nodeType); // 1,表示此节点为元素节点
- children 可以获取所有的子元素节点 也是实际开发中最常用的
console.log(ul.children); // HTMLCollection(4) [li, li, li, li]
- firstChild 第一个子节点 ;lastChild 最后一个子节点
console.log(ul.firstChild); // #text
console.log(ul.lastChild); // #text
- firstElementChild 第一个子元素节点 ; lastElementChild 最后一个子元素节点
console.log(ul.firstElementChild); // <li>...</li>
console.log(ul.lastElementChild); // <li>...</li>
- 开发中最常用
console.log(ul.children[0]);
console.log(ul.children[ul.children.length - 1]);
实例,仿微博下拉案例
效果预览:
虽然类似于上一个例子,但完全没必要用自定义属性来做对应关系
节点的逻辑性很强,在这方面有很好的体现,通过对html编写,使其更满足效果展示的逻辑结构:
<body>
<ul class="nav">
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li>
<a href="">私信</a>
</li>
<li>
<a href="">评论</a>
</li>
<li>
<a href="">@我</a>
</li>
</ul>
</li>
</ul>
</body>
css:
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
a {
text-decoration: none;
font-size: 14px;
}
.nav {
margin: 100px;
}
.nav>li { /* 子代选择器 */
position: relative;
float: left;
width: 80px;
height: 41px;
text-align: center;
}
.nav li a {
display: block;
width: 100%;
height: 100%;
line-height: 41px;
color: #333;
}
.nav>li>a:hover {
background-color: #eee;
}
.nav ul {
display: none;
position: absolute;
top: 41px;
left: 0;
width: 100%;
border-left: 1px solid #fecc5b;
border-right: 1px solid #fecc5b;
}
.nav ul li {
border-bottom: 1px solid #fecc5b;
}
.nav ul li a:hover {
background-color: #fff5da;
}
</style>
js:
<script>
// 仿微博下拉菜单
var nav = document.querySelector('.nav');
var lis = nav.children;
for(var i = 0; i < lis.length; i++){
lis[i].onmouseover = function(){
this.children[1].style.display = 'block'
}
lis[i].onmouseout = function(){
this.children[1].style.display = 'none'
}
}
</script>
节点的创建、添加与删除
html:
<body>
<div>我是div</div>
<span>我是span</span>
<ul>
<li>123</li>
</ul>
<button>删除</button>
</body>
- 兄弟节点
nextSibiling 返回下一个兄弟节点 ; previousSibiling 返回上一个兄弟节点
会返回所有类型的节点(包括元素节点,文本节点)
var div = document.querySelector('div')
console.log(div.nextSibling); // #text
console.log(div.previousSibling); // #text
nextElementSibling 返回下一个兄弟元素节点 ; previousElementSibling 返回上一个兄弟元素节点
如没有兄弟节点则返回null
IE 9.0 以上支持
console.log(div.nextElementSibling); // <span>...</span>
console.log(div.previousElementSibling); // null
- 创建节点
var li1 = document.createElement('li');
var li2 = document.createElement('li');
- 添加节点
node.appendChild(child) 在node后追加元素,类似于数组中的push
document.querySelector('ul').appendChild(li1);
node.insertBefore(child,指定元素) 在指定元素前添加节点
var ul = document.querySelector('ul');
ul.insertBefore(li2,ul.children[0]);
往页面里添加元素需要执行以上两个步骤:1.创建节点,2.添加节点
- 删除节点 node.removeChild(child)
var btn = document.querySelector('button');
btn.onclick = function(){
var li = ul.children[0];
ul.removeChild(li);
}
节点克隆
var ul = document.querySelector('ul');
// 克隆节点 node.cloneNode();
// node.cloneNode() ;括号内参数可以填true或false(或者为空)
// 如果参数为空(false),则表示为浅拷贝,只复制标签而不复制里面的内容
// 如果参数为true,则表示深拷贝,复制标签的所有内容
// var li1 = ul.children[0].cloneNode();
var li1 = ul.children[0].cloneNode(true);
ul.appendChild(li1);
实例,动态表格生成
html:
<body>
<table cellspacing="0">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>
css:
<style>
table {
width: 500px;
margin: 100px auto;
border-collapse: collapse;
text-align: center;
}
td,
th {
border: 1px solid #333;
}
thead tr {
height: 40px;
background-color: #ccc;
}
</style>
js:
<script>
// 动态生成表格
// 数据存储
var data = [{
name: 'student1',
subject: 'Computer Science',
score: '98',
}, {
name: 'student2',
subject: 'Computer Science',
score: '88',
}, {
name: 'student3',
subject: 'Computer Science',
score: '90',
}, {
name: 'student4',
subject: 'Computer Science',
score: '78',
}, {
name: 'student5',
subject: 'Computer Science',
score: '69',
}];
// console.log(data);
// 生成表格行
var tbody = document.querySelector('tbody');
for(var i = 0; i < data.length; i++){
// 创建表格行节点
var tr = document.createElement('tr');
// 添加表格行节点
tbody.appendChild(tr);
// 对象属性遍历
for(var k in data[i]){
// 创建单元格节点
var td = document.createElement('td');
td.innerHTML = data[i][k]; // 单元格赋值
// 添加单元格节点
tr.appendChild(td);
}
// 添加删除按钮
var del = document.createElement('td');
del.innerHTML = "<a href='javascript:;'>delete</a>";
tr.appendChild(del);
}
// 删除按钮添加事件
var dels = document.querySelectorAll('a');
for (var i = 0; i < dels.length; i++){
dels[i].onclick = function(){
tbody.removeChild(this.parentNode.parentNode); // <a> --> td --> tr
}
}
</script>