API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,无需理解其内部工作机制细节,只需直接调用使用即可。
Web API 是浏览器提供的一套操作浏览器功能和页面元素的 API ( BOM 和 DOM )。Web API 主要是针对于浏览器提供的接口,主要针对于浏览器做交互效果。
此处的 Web API 特指浏览器提供的一系列API(很多函数或对象方法),即操作网页的一系列工具。例如:操作html标签、操作页面地址的方法。
MDN 详细 API : https://developer.mozilla.org/zh-CN/docs/Web/API
文档对象模型(Document Object Model,简称DOM),是 W3C 组织推荐的处理可扩展标记语言(html或者xhtml)的标准编程接口。
W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。
DOM是W3C组织制定的一套处理 html和xml文档的规范,所有的浏览器都遵循了这套标准。
DOM树 又称为文档树模型,把文档映射成树形结构,通过节点对象对其处理,处理的结果可以加入到当前的页面。
想要操作页面上的某部分(显示/隐藏,动画),需要先获取到该部分对应的元素,再对其进行操作。
获取页面中的元素可以使用以下几种方式: 根据ID获取、根据标签名获取、通过 HTML5 新增的方法获取、特殊元素获取。
<body>
<div id="time">2019-9-9</div>
<script>
// 因为文档页面从上往下加载,所以先得有标签 所以script写到标签的下面
var timer = document.getElementById('time');
console.log(timer);
console.log(typeof timer);
// console.dir 打印返回的元素对象 更好的查看里面的属性和方法
console.dir(timer);
</script>
</body>
<body>
<ul>
<li>知否知否,应是等你好久11</li>
<li>知否知否,应是等你好久22</li>
<li>知否知否,应是等你好久33</li>
<li>知否知否,应是等你好久44</li>
<li>知否知否,应是等你好久55</li>
</ul>
<ul id="nav">
<li>生僻字</li>
<li>生僻字</li>
<li>生僻字</li>
<li>生僻字</li>
<li>生僻字</li>
</ul>
<script>
// 1.返回的是 获取过来元素对象的集合 以伪数组的形式存储的
var lis = document.getElementsByTagName('li');
console.log(lis);
console.log(lis[0]);
// 2. 想要依次打印里面的元素对象我们可以采取遍历的方式
for (var i = 0; i < lis.length; i++) {
console.log(lis[i]);
}
// 3. element.getElementsByTagName() 可以得到这个元素里面的某些标签
var nav = document.getElementById('nav'); // 这个获得nav 元素
var navLis = nav.getElementsByTagName('li');
console.log(navLis);
</script>
</body>
注意:getElementsByTagName()获取到是动态集合,即:当页面增加了标签,这个集合中也就增加了元素。
querySelector 和 querySelectorAll里面的选择器需要加符号,比如:document.querySelector(‘#nav’);
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
// 1. getElementsByClassName 根据类名获得某些元素集合
var boxs = document.getElementsByClassName('box');
console.log(boxs);
// 2. querySelector 返回指定选择器的第一个元素对象 切记 里面的选择器需要加符号 .box #nav
var firstBox = document.querySelector('.box');
console.log(firstBox);
var nav = document.querySelector('#nav');
console.log(nav);
var li = document.querySelector('li');
console.log(li);
// 3. querySelectorAll()返回指定选择器的所有元素对象集合
var allBox = document.querySelectorAll('.box');
console.log(allBox);
var lis = document.querySelectorAll('li');
console.log(lis);
</script>
</body>
// 获取特殊元素
console.log(document.body);
console.log(document.documentElement);
JavaScript 有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。
网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,可以在用户点击某按钮时产生一个 事件,然后去执行某些操作。事件三要素:
<body>
<button id="btn">唐伯虎</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function() {
alert('点秋香');
}
</script>
</body>
常见的鼠标事件:
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起发 |
onmousedown | 鼠标按下触发 |
JavaScript的 DOM 操作可以改变网页内容、结构和样式,利用 DOM 操作元素来改变元素里面的内容、属性等。(注意:这些操作都是通过元素对象的属性实现的)
element.innerText 从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉
element.innerHTML 起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
<body>
<button>显示当前系统时间</button>
<div>某个时间</div>
<p>1123</p>
<script>
// 当我们点击了按钮, div里面的文字会发生变化
// 1. 获取元素
var btn = document.querySelector('button');
var div = document.querySelector('div');
// 2.注册事件
btn.onclick = function() {
// div.innerText = '2019-6-6';
div.innerHTML = getDate();
}
function getDate() {
var date = new Date();
// 我们写一个 2019年 5月 1日 星期三
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay();
return '今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day];
}
</script>
</body>
获取内容时,innerText会去除空格和换行,而innerHTML会保留空格和换行
设置内容时,innerText不会识别html,而innerHTML会识别
<body>
<div></div>
<p>
我是文字
<span>123</span>
</p>
<script>
// innerText 和 innerHTML的区别
// 1. innerText 不识别html标签 非标准 去除空格和换行
var div = document.querySelector('div');
// div.innerText = '今天是: 2019';
// 2. innerHTML 识别html标签 W3C标准 保留空格和换行的
div.innerHTML = '今天是: 2019';
// 这两个属性是可读写的 可以获取元素里面的内容
var p = document.querySelector('p');
console.log(p.innerText);
console.log(p.innerHTML);
</script>
</body>
获取属性的值
元素对象.属性名
设置属性的值
元素对象.属性名 = 值
<body>
<button id="ldh">刘德华</button>
<button id="zxy">张学友</button> <br>
<img src="images/ldh.jpg" alt="" title="刘德华">
<script>
// 修改元素属性 src
// 1. 获取元素
var ldh = document.getElementById('ldh');
var zxy = document.getElementById('zxy');
var img = document.querySelector('img');
// 2. 注册事件 处理程序
zxy.onclick = function() {
img.src = 'images/zxy.jpg';
img.title = '张学友思密达';
}
ldh.onclick = function() {
img.src = 'images/ldh.jpg';
img.title = '刘德华';
}
</script>
</body>
利用 DOM 可以操作如下表单元素的属性:
type、value、checked、selected、disabled
表单元素中有一些属性如:disabled、checked、selected,属性的值是布尔型。
<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 我们想要这个按钮 button禁用
// btn.disabled = true;
this.disabled = true;
// this 指向的是事件函数的调用者 btn
}
</script>
</body>
显示密码案例:
var pwd = document.getElementById('pwd');
var eye = document.getElementById('eye');
var flag = true;
eye.onclick = function () {
if (flag) {
flag = false;
pwd.type = 'text';
eye.src = 'images/open.png';
} else {
flag = true;
pwd.type = 'password';
eye.src = 'images/close.png';
}
}
可以通过 JS 修改元素的大小、颜色、位置等样式:
元素对象的style属性也是一个对象,元素对象.style.样式属性 = 值;
JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor;JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
隐藏二维码示例:
var close = document.querySelector('.close');
var code = document.querySelector('.closeQrcode');
close.onclick = function () {
code.style.display = 'none';
}
循环精灵图背景示例:
var imageLabels = document.getElementsByClassName('image');
for (var i = 0; i < imageLabels.length; i++) {
var imageLabel = imageLabels[i];
var yPosition = (24 + 20)*i;
imageLabel.style.backgroundPosition = '0 -' + yPosition + 'px';
}
显示、隐藏文本框内容示例:
var searchBar = document.getElementById('searchBar');
searchBar.onfocus = function () {
this.value = null;
}
searchBar.onblur = function () {
this.value = '手机';
}
如果样式修改较多,可以采取操作类名方式更改元素样式。class因为是个保留字,因此使用className来操作元素类名属性。className 会直接更改元素的类名,所以会覆盖原先的类名。如果想要保留原先的类名,可以这么做使用空格拼接多个类名。
var className = document.querySelector('.className');
console.log(className);
className.onclick = function () {
this.className = 'changeClass';
}
密码框格式提示错误信息示例:
var ipt = document.querySelector('.ipt');
var msg = document.querySelector('.message');
ipt.onblur = function () {
if (this.value.length < 6 || this.value.length > 16) {
msg.className = 'message wrong';
msg.innerHTML = '您输入的位数不对,要求6~16位!';
} else {
msg.className = 'message right';
msg.innerHTML = '密码输入正确!';
}
}
如果有同一组元素,想要某一个元素实现某种样式, 需要用到循环的排他思想算法:
var btns = document.getElementsByClassName('other');
for(var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
for(var i = 0; i < btns.length; i++) {
btns[i].style.backgroundColor = '';
}
this.style.backgroundColor = 'pink';
}
}
换肤案例:
表格隔行变色案例:
全选案例:
获取属性值:
设置属性值:
移除属性:
var custom = document.getElementById('custom');
var getB = document.getElementById('getB');
var setB = document.getElementById('setB');
var removeB = document.getElementById('removeB');
getB.onclick = function() {
alert('id: ' + custom.id + '; data-index: ' + custom.getAttribute('data-index'));
}
setB.onclick = function() {
custom.id = 'customs';
custom.setAttribute('data-index', 2);
}
removeB.onclick = function() {
custom.removeAttribute('id');
custom.removeAttribute('data-index');
}
tab栏切换案例:
var lis = document.querySelector('.tab_list').querySelectorAll('li');
var divs = document.querySelector('.tab_con').querySelectorAll('div')
for (var i = 0; i < lis.length; i++) {
// 设置索引
lis[i].setAttribute('data-index', i)
lis[i].onclick = function() {
for (var i = 0; i < lis.length; i++) {
lis[i].className = '';
}
this.className = 'current';
for (var i = 0; i < divs.length; i++) {
divs[i].style.display = 'none';
}
var index = this.getAttribute('data-index')
divs[index].style.display = 'block';
}
}
H5自定义属性:
自定义属性目的是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。自定义属性获取是通过getAttribute(‘属性’) 获取。
但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。H5规定自定义属性data-开头做为属性名并且赋值。比如
或者使用 JS 设置 element.setAttribute(‘data-index’, 2)获取H5自定义属性:
var customH5 = document.getElementById('customH5');
var getBH5 = document.getElementById('getBH5');
var setBH5 = document.getElementById('setBH5');
getBH5.onclick = function() {
alert('data-index: ' + customH5.getAttribute('data-index') + '; data-first-name: ' + customH5.dataset['firstName']);
console.log(customH5.dataset);
console.log(customH5.dataset['index']);
console.log(customH5.dataset.firstName);
}
setBH5.onclick = function() {
customH5.setAttribute('data-index', 2);
customH5.setAttribute('data-first-name', 'b');
}
获取元素通常使用两种方式:
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。在实际开发中,节点操作主要操作的是元素节点:
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
node.parentNode
1.parentNode.childNodes(标准) 返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。
如果只想要获得里面的元素节点,则需要专门处理。 所以一般不提倡使用childNodes
var ul = document.querySelector(‘ul’);
for(var i = 0; i < ul.childNodes.length;i++) {
if (ul.childNodes[i].nodeType == 1) {
// ul.childNodes[i] 是元素节点
console.log(ul.childNodes[i]);
}
}
实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性问题,那么如何获取第一个子元素节点或最后一个子元素节点呢? 解决方案:
- 我是li
- 我是li
- 我是li
- 我是li
下拉菜单案例:
var lis = document.querySelector('.nav').children;
for (let index = 0; index < lis.length; index++) {
const element = lis[index];
element.onmouseover = function() {
this.children[1].style.display = 'block';
}
element.onmouseout = function() {
this.children[1].style.display = 'none';
}
}
let brother = document.querySelector('.brother');
console.log(brother.nextSibling);
console.log(brother.previousSibling);
console.log(brother.nextElementSibling);
console.log(brother.previousElementSibling);
如果需要获取的是兄弟元素节点,又解决兼容性问题,可以封装如下函数:
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
document.createElement(‘tagName’) 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据需求动态生成的,所以也称为动态创建元素节点。
node.removeChild(child) 方法从 DOM 中删除一个子节点,返回删除的节点。
let append = document.querySelector('.append');
let li2 = document.createElement('li');
li2.innerHTML = '2';
append.appendChild(li2);
let li3 = document.createElement('li');
li3.innerHTML = '3';
append.insertBefore(li3, append.children[0]);
var deleteEle = document.querySelector('.delete');
deleteEle.onclick = function() {
if (append.children.length > 0) {
append.removeChild(append.children[0]);
}
this.disabled = append.children.length == 0;
};
阻止链接跳转需要添加 javascript:void(0);
或者 javascript:;
留言板案例:
let textDiv = document.querySelector('.textView');
let textView = textDiv.querySelector('textarea');
let publish = textDiv.querySelector('button');
publish.onclick = function() {
if (textView.value.length > 0) {
let li = document.createElement('li');
li.innerHTML = textView.value + '删除';
let ul = textDiv.querySelector('ul');
ul.insertBefore(li, ul.children[0]);
// ul.appendChild(li)
textView.value = null
let as = textDiv.getElementsByTagName('a');
for (let i = 0; i < as.length; i++) {
as[i].onclick = function() {
ul.removeChild(this.parentNode);
};
}
} else {
alert('请输入内容!');
}
};
node.cloneNode() 方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点:
var cloneUl = document.querySelector('.clone');
var li = cloneUl.children[0];
cloneUl.appendChild(li.cloneNode());
cloneUl.insertBefore(li.cloneNode(true), li);
表格动态生成案例:
var datas = [{
name: '魏璎珞',
project: 'javascrit',
score: '100',
}, {
name: '宏历',
project: 'javascrit',
score: '99',
}, {
name: '傅恒',
project: 'javascrit',
score: '98',
}, {
name: '明玉',
project: 'javascrit',
score: '97',
}];
var tbody = document.querySelector('tbody');
for (let index = 0; index < datas.length; index++) {
var tr = document.createElement('tr');
for (const key in datas[index]) {
var td = document.createElement('td');
td.innerHTML = datas[index][key];
tr.appendChild(td);
}
var td = document.createElement('td');
td.innerHTML = '删除';
tr.appendChild(td);
tbody.appendChild(tr);
}
var as = tbody.getElementsByTagName('a');
for (let index = 0; index < as.length; index++) {
as[index].onclick = function() {
tbody.removeChild(this.parentNode.parentNode);
};
}
document.write()、element.innerHTML、document.createElement()的区别:
总结:不同浏览器下,innerHTML 效率要比 creatElement 高
<script>
// 三种创建元素方式区别
// 1. document.write() 创建元素 如果页面文档流加载完毕,再调用这句话会导致页面重绘
var btn = document.querySelector('button');
btn.onclick = function() {
document.write('123');
}
// 2. innerHTML 创建元素
var inner = document.querySelector('.inner');
for (var i = 0; i <= 100; i++) {
inner.innerHTML += '百度'
}
var arr = [];
for (var i = 0; i <= 100; i++) {
arr.push('百度');
}
inner.innerHTML = arr.join('');
// 3. document.createElement() 创建元素
var create = document.querySelector('.create');
for (var i = 0; i <= 100; i++) {
var a = document.createElement('a');
create.appendChild(a);
}
</script>
innerHTML字符串拼接方式(效率低)
<script>
function fn() {
var d1 = +new Date();
var str = '';
for (var i = 0; i < 1000; i++) {
document.body.innerHTML += '';
}
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>
createElement方式(效率一般)
<script>
function fn() {
var d1 = +new Date();
for (var i = 0; i < 1000; i++) {
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '2px';
div.style.border = '1px solid red';
document.body.appendChild(div);
}
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>
innerHTML数组方式(效率高)
<script>
function fn() {
var d1 = +new Date();
var array = [];
for (var i = 0; i < 1000; i++) {
array.push('');
}
document.body.innerHTML = array.join('');
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>