API概念
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
Web API的概念
浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)
此处的Web API特指浏览器提供的API(一组方法),Web API在后面的课程中有其它含义
掌握常见浏览器提供的API的调用方式
MDN
定义了JavaScript 的语法规范
JavaScript的核心,描述了语言的基本语法和数据类型,ECMAScript是一套标准,定义了一种语言的标准与具体实现无关
一套操作浏览器功能的API
通过BOM可以操作浏览器窗口,比如:弹出框、控制浏览器跳转、获取分辨率等
一套操作页面元素的API
DOM可以把HTML看做是文档树,通过DOM提供的API可以对树上的节点进行操作
DOM的概念
文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口。它是一种与平台和语言无关的应用程序接口(API),它可以动态地访问程序和脚本,更新其内容、结构和www文档的风格(目前,HTML和XML文档是通过说明部分定义的)。文档可以进一步被处理,处理的结果可以加入到当前的页面。DOM是一种基于树的API文档,它要求在处理过程中整个文档都表示在存储器中。
DOM又称为文档树模型
DOM经常进行的操作
为什么要获取页面元素
例如:我们想要操作页面上的某部分(显示/隐藏,动画),需要先获取到该部分对应的元素,才进行后续操作
根据id获取元素
var div = document.getElementById('main');
console.log(div);
// 获取到的数据类型 HTMLDivElement,对象都是有类型的
注意:由于id名具有唯一性,部分浏览器支持直接使用id名访问元素,但不是标准方式,不推荐使用。
根据标签名获取元素
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
console.log(div);
}
根据name获取元素*
var inputs = document.getElementsByName('hobby');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
console.log(input);
}
根据类名获取元素*
var mains = document.getElementsByClassName('main');
for (var i = 0; i < mains.length; i++) {
var main = mains[i];
console.log(main);
}
根据选择器获取元素*
var text = document.querySelector('#text');
console.log(text);
var boxes = document.querySelectorAll('.box');
for (var i = 0; i < boxes.length; i++) {
var box = boxes[i];
console.log(box);
}
总结
掌握
getElementById()
getElementsByTagName()
了解
getElementsByName()
getElementsByClassName()
querySelector()
querySelectorAll()
事件:触发-响应机制
事件三要素
事件的基本使用
var box = document.getElementById('box');
box.onclick = function() {
console.log('代码会在box被点击后执行');
};
案例
// 点击按钮弹出提示框
btn = document.getElementById('btn');
// 给按钮注册事件
btn.onclick = function () {
alert('点我了');
}
// 点击按钮切换图片
// 获取元素
var btn = document.getElementById('btn');
var mv = document.getElementById('mv');
var flag = 1;
// 注册按钮事件
btn.onclick = function () {
// 切换图片
if (flag === 1) {
mv.src = 'images/b.jpg';
flag = 2;
} else {
mv.src = 'images/a.jpg';
flag = 1;
}
}
var link = document.getElementById('link');
console.log(link.href);
console.log(link.title);
var pic = document.getElementById('pic');
console.log(pic.src);
案例:
// 点击按钮显示隐藏div
// 获取元素
var btn = document.getElementById('btn');
var box = document.getElementById('box');
var flag = 1;
// 注册事件
btn.onclick = function () {
// 控制显示隐藏
if (flag === 1) {
this.value = '显示';
box.className = 'hidden';
flag = 2;
} else {
this.value = '隐藏';
box.className = 'block';
flag = 1;
}
}
美女相册案例HTML:
<h2>美女画廊h2>
<div id="imagegallery">
<a href="images/1.jpg" title="美女A">
<img src="images/1-small.jpg" width="100" alt="美女1">
a>
<a href="images/2.jpg" title="美女B">
<img src="images/2-small.jpg" width="100" alt="美女2">
a>
<a href="images/3.jpg" title="美女C">
<img src="images/3-small.jpg" width="100" alt="美女3">
a>
<a href="images/4.jpg" title="美女D">
<img src="images/4-small.jpg" width="100" alt="美女4">
a>
div>
<div style="clear: both">div>
<img id="image" src="images/placeholder.png" alt="" width="450">
<p id="des">选择一个图片p>
美女相册案例JS:
// 1 获取到所有的a标签
var imagegallery = document.getElementById('imagegallery');
var links = imagegallery.getElementsByTagName('a');
// 2 给所有的a标签注册事件
for (var i = 0; i < links.length; i++) {
var link = links[i];
link.onclick = function () {
// 4 切换图片
// 获取占位大的img
var image = document.getElementById('image');
// 把img标签的属性 设置为点前点击a的标签的href
image.src = this.href;
// 5 设置p标签的内容
var des = document.getElementById('des');
// link 中的 title
// 设置 p 中的内容
// console.dir(des)
des.innerHTML = this.title;
// 3 取消a 的默认注册事件
return false;
}
}
var box = document.getElementById('box');
box.innerHTML = '我是文本我会生成为标签
';
console.log(box.innerHTML);
box.innerText = '我是文本我不会生成为标签
';
console.log(box.innerText);
" "
' '
& &
< < // less than 小于
> > // greater than 大于
空格
© ©
// 内容标签,以 HTML 形式显示出来
box.innerHTML = "黑马程序员";
// 原封不动的显示出来
box.innerText = '黑马程序员';
// 如何知道 浏览器是否支持元素的某个属性
var box = document.getElementById('box');
console.log(getInnerText(box));
// 当属性不存在的时候 返回的是 undefined
function getInnerText(element) {
if (typeof element.innerText === 'string') {
return element.innerText;
} else {
return element.textContent;
}
}
案例
// 获取元素
var btn = document.getElementById('btn');
var txt = document.getElementById('txt');
// 注册点击事件
btn.onclick = function () {
console.log(txt.value);
console.log(txt.type);
// 当 html 中的标签的属性只有一个的时候
// 在 DOM 中的类型为 布尔类型
console.log(txt.disabled)
txt.disabled = true; // 禁用,默认为false
}
// 获取所有文本框的值
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
// 判断是否是文本框
if (input.type === 'text') {
input.value = i;
}
}
// 点击按钮,获取所有文本框的值并使用 | 分割输出
var btn = document.getElementById('btn');
btn.onclick = function () {
var array = [];
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
// 判断是否是文本框
if (input.type === 'text') {
array.push(input.value);
}
}
// 拼接
var s = array.join('|');
console.log(s)
}
// 检测用户名是否是 3-6 位,密码是 6-8 位,如果不满足要求高亮显示文本框
var btnLogin = document.getElementById('btnLogin');
btnLogin.onclick = function () {
// 检测用户名是否是 3-6 位,密码是 6-8 位
var txtUserName = document.getElementById('txtUserName');
var txtUserPassword = document.getElementById('txtUserPassword');
// 检测用户名是否是 3-6 位
if (txtUserName.value.length < 3 || txtUserName.value.length > 6) {
txtUserName.className = 'bg';
return;
} else {
txtUserName.className = '';
}
// 密码是 6-8 位
if (txtUserPassword.value.length < 6 || txtUserPassword.value.length > 8) {
txtUserPassword.className = 'bg';
return;
} else {
txtUserPassword.className = '';
}
console.log('执行登陆')
}
// 1 给按钮注册事件
var btnSet = document.getElementById('btnSet');
btnSet.onclick = function () {
// 2 获取下拉框的所有option
var selCities = document.getElementById('selCities');
var options = selCities.getElementsByTagName('option');
// 3 随机生成索引
// Math.random() -> [0, 1)
// Math.random() * 5 -> [0, 5)
var randomIndex = parseInt(Math.random() * options.length);
// 4 根据索引获取 oprion,并让 option 选中
var option = options[randomIndex];
option.selected = true;
}
// 当文本框获得焦点,如果文本框的内容是 请输入搜索关键字 清空文本框并让字体变黑色
// 当文本框是去焦点,如果文本框里的内容为空,还原文本框里的文字,并让字体变为灰色
var txtSearch = document.getElementById('txtSearch');
// 获取焦点的时间 focus
txtSearch.onfocus = function () {
if (this.value === '请输入搜索关键字') {
this.value = '';
this.className = 'black';
}
}
// 当文本框是去焦点,如果文本框里的内容为空,还原文本框的文字,并让文字变为灰色
txtSearch.onblur = function () {
if (this.value.length === 0 || this.value === '请输入搜索关键字') {
this.value = '请输入搜索关键字';
this.className = 'gray';
}
}
// 全选功能
// 获取父checkbox,注册点击事件
var j_cbAll = document.getElementById('j_cbAll');
var j_tb = document.getElementById('j_tb');
var inputs = j_tb.getElementsByTagName('input');
j_cbAll.onclick = function () {
for ( var i = 0; i < inputs.length; i++) {
input = inputs[i];
if ( input.type === 'checkbox') {
input.checked = this.checked;
}
}
}
// 2 当点击子的checkbox,如果所有的子的checkbox都被选中了,父的checkbox也被选中
// 如果有一个子的checkbox 没有被选中,父的checkbox也不被选中
for( var i = 0; i < inputs.length; i++) {
input = inputs[i];
// 判断是否是 checkbox
if (input.type !== 'checkbox') {
continue;
}
input.onclick = function () {
checkAllCheckbox();
}
}
function checkAllCheckbox() {
// 判断所有的子的checkbox都被选中
var isAllChecked = true;
for( var i = 0; i < inputs.length; i++) {
input = inputs[i];
if(!input.checked) {
isAllChecked = false;
}
}
j_cbAll.checked = isAllChecked;
}
// 3 反选
// 给反选按钮点击事件
var btn = document.getElementById('btn');
btn.onclick = function () {
for (var i = 0; i < inputs.length; i++) {
input = inputs[i];
if (input.type !== 'checkbox') {
continue;
}
var input = inputs[i];
input.checked = !input.checked;
}
// 判断父的checkbox
checkAllCheckbox();
}
使用style方式设置的样式显示在标签行内
var box = document.getElementById('box');
box.style.width = '100px';
box.style.height = '100px';
box.style.backgroundColor = 'red';
注意
通过样式属性设置宽高、位置的属性类型是字符串,需要加上px
修改标签的className属性相当于直接修改标签的类名
var box = document.getElementById('box');
box.className = 'show';
案例
// 是否开灯 false 关灯状态 true 开灯状态
var isOpen = true;
document.getElementById('btn').onclick = function () {
if (isOpen) {
document.body.style.backgroundColor = 'black';
this.value = '开灯';
isOpen = false;
} else {
document.body.style.backgroundColor = 'white';
this.value = '关灯';
isOpen = true;
}
}
document.getElementById('btn').onclick = function () {
// 当设置宽度和高度的时候必须带单位,如果不带单位,有错误
var box = my$('box');
box.style.width = '200px';
box.style.height = '200px';
box.style.backgroundColor = 'red';
}
// 当鼠标移入 onmouseover
// 当鼠标移出 onmouseout
var nodeSmall = document.getElementById('node_small');
nodeSmall.onmouseover = function () {
// my$('er').className = 'erweima show';
my$('er').className = my$('er').className.replace('hide', 'show');
}
nodeSmall.onmouseout = function () {
// my$('er').className = 'erweima hide';
my$('er').className = my$('er').className.replace('show', 'hide');
}
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
// 判断input是否是文本框
if (input.type !== 'text') {
continue;
}
// 让当前正在输入的文本框 高亮显示
input.onfocus = function () {
// 让所有的文本框去掉高亮的效果
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
if (input.type !== 'text') {
continue;
}
// 去除所有文本框高亮显示
input.style.backgroundColor = '';
}
// 当前文本框高亮显示
this.style.backgroundColor = 'lightgray';
}
}
document.getElementById('btn').onclick = function () {
var box = my$('box');
// 使用style 设置大小和位置的时候 数字必须带单位
box.style.width = '200px';
box.style.height = '200px';
box.style.position = 'absolute';
box.style.left = '200px';
box.style.top = '200px';
}
// 1 隔行变色
// 获取到所有的li,判断奇数行和偶数行
var mv = document.getElementById('mv');
var lists = mv.getElementsByTagName('li');
for (var i = 0; i < lists.length; i++) {
var li = lists[i];
// 判断当前的li 是奇数行 还是偶数行
if (i % 2 === 0) {
// i是偶数 , 但是当前是奇数行
// 设置奇数行的背景颜色
li.style.backgroundColor = 'red';
} else {
// 设置偶数行的背景颜色
li.style.backgroundColor = 'green';
}
}
// 2 鼠标放上高亮显示
// 2.0 给所有的li 注册事件 鼠标经过和鼠标离开的两个事件
for (var i = 0; i < lists.length; i++) {
var li = lists[i];
// 2.1 鼠标放到li上,高亮显示当前的li
var bg;
li.onmouseover = function () {
// 鼠标放到li上的时候,应该记录li当前的颜色
bg = this.style.backgroundColor;
this.style.backgroundColor = 'yellow';
}
// 2.2 鼠标离开li,还原原来的颜色
li.onmouseout = function () {
// 鼠标离开,还原原来的颜色
this.style.backgroundColor = bg;
}
}
// 1 鼠标放到tab栏高亮显示,其它tab栏取消高亮
var hd = my$('hd');
var spans = hd.getElementsByTagName('span');
for (var i = 0; i < spans.length; i++) {
var span = spans[i];
// 通过自定义属性,记录当前span的索引
span.setAttribute('index', i);
// 注册事件
span.onmouseover = fn
}
// 鼠标经过的事件处理函数
function fn() {
// 让所有的span取消高亮显示
for (var i = 0; i < spans.length; i++) {
var span = spans[i];
span.className = '';
}
// 当前的span高亮显示
this.className = 'current';
// 2 tab栏对应的div 显示,其它div隐藏
// 所有的div 隐藏
var bd = my$('bd');
var divs = bd.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
div.className = '';
}
// 当前span对应的div显示
// 获取自定义属性的值
var index = parseInt(this.getAttribute('index')) ;
divs[index].className = 'current';
}
document.write()
document.write('新设置的内容标签也可以生成
');
innerHTML
var box = document.getElementById('box');
box.innerHTML = '新内容新标签
';
document.createElement()
var div = document.createElement('div');
document.body.appendChild(div);
性能问题
案例:
动态创建列表,高亮显示
//动态创建列表,高亮显示
var datas = ['西施', '貂蝉', '凤姐', '芙蓉姐姐'];
// 点击按钮 动态创建列表 鼠标放上高亮显示
my$('btn').onclick = function () {
// 动态创建ul
var ul = document.createElement('ul');
my$('box').appendChild(ul);
for (i = 0; i < datas.length; i++) {
var li = document.createElement('li');
ul.appendChild(li);
// 设置li中的显示的内容
// innerText
// li.innerText = datas[i];
setInnerText(li, datas[i]);
// 给 li 注册事件
li.onmousemove = liMouseOver;
li.onmouseout = liMouseOut;
}
}
function liMouseOver() {
// 鼠标经过高亮显示
this.style.backgroundColor = 'red';
}
function liMouseOut() {
this.style.backgroundColor = '';
}
// 设置标签之间的内容
function setInnerText(element, content) {
// 判断当前浏览器是否支持 innerText
if (typeof element.innerText === 'string') {
element.innerText = content;
} else {
element.textContent = content;
}
}
根据数据动态创建表格
// var s = {name: 'zs', subject: '语文', score: 90};
// 模拟数据
var datas = [
{name: 'zs', subject: '语文', score: 90},
{name: 'zs2', subject: '语文2', score: 90},
{name: 'zs3', subject: '语文3', score: 90},
{name: 'zs4', subject: '语文4', score: 90},
{name: 'zs5', subject: '语文5', score: 90},
{name: 'zs6', subject: '语文6', score: 90},
];
// 表头数据
var headDate = ['姓名', '科目', '成绩', '操作'];
// 1 创建表格
var table = document.createElement('table');
my$('box').appendChild(table);
table.border = '1px';
table.width = '400px';
// 2 创建表头
var thead = document.createElement('thead');
table.appendChild(thead);
var tr = document.createElement('tr');
thead.appendChild(tr);
tr.style.height = '40px';
tr.style.backgroundColor = 'lightgray';
for (var i = 0; i < headDate.length; i++) {
var th = document.createElement('th');
tr.appendChild(th);
// th.innerText
setInnerText(th, headDate[i]);
}
var tbody = document.createElement('tbody');
tbody.style.textAlign = 'center';
table.appendChild(tbody);
for (var i = 0; i < datas.length; i++) {
// {name: 'zs', subject: '语文', score: 90},
var tr = document.createElement('tr');
tbody.appendChild(tr);
var data = datas[i];
for ( var key in data) {
var td = document.createElement('td');
tr.appendChild(td);
setInnerText(td, data[key]);
}
// 生成删除对应的列
var td = document.createElement('td');
tr.appendChild(td);
var link = document.createElement('a');
td.appendChild(link);
link.href = 'javascript:void(0)';
setInnerText(link, '删除');
link.onclick = linkDelete;
}
function linkDelete() {
// removeChild
// 获取父元素
var tr = this.parentNode.parentNode;
tbody.removeChild(tr);
return false;
}
var body = document.body;
var div = document.createElement('div');
body.appendChild(div);
var firstEle = body.children[0];
body.insertBefore(div, firstEle);
body.removeChild(firstEle);
var text = document.createElement('p');
body.replaceChild(text, div);
案例:
选择水果
var all = my$('all');
var select = my$('select');
// 1 全部选择
my$('btn1').onclick = function () {
// 移走 children 索引会变化
//for (var i = 0; i < all.children.length; i++) {
// select.appendChild(all.children[i]);
//}
//for (var i = all.children.length -1; i >= 0; i--) {
// select.appendChild(all.children[i]);
//}
var len = all.children.length;
for (var i = 0; i < len; i++) {
select.appendChild(all.children[0]);
}
}
// 2 移动选中的水果
my$('btn3').onclick = function () {
// 找到所有选中的option
var array = []; // 存储选中的option
for (var i = 0; i < all.children.length; i++) {
var option = all.children[i];
if (option.selected) {
array.push(option);
option.selected = false;
}
}
// 把数组的option移动到第二个select
for ( var i = 0; i < array.length; i++) {
select.appendChild(array[i]);
}
}
function Node(option) {
this.id = option.id || '';
this.nodeName = option.nodeName || '';
this.nodeValue = option.nodeValue || '';
this.nodeType = 1;
this.children = option.children || [];
}
var doc = new Node({
nodeName: 'html'
});
var head = new Node({
nodeName: 'head'
});
var body = new Node({
nodeName: 'body'
})
doc.children.push(head);
doc.children.push(body);
var div = new Node({
nodeName: 'div',
nodeValue: 'haha',
});
var p = new Node({
nodeName: 'p',
nodeValue: '段落'
})
body.children.push(div);
body.children.push(p);
function getChildren(ele) {
for(var i = 0; i < ele.children.length; i++) {
var child = ele.children[i];
console.log(child.nodeName);
getChildren(child);
}
}
getChildren(doc);
var box = document.getElementById('box');
console.log(box.parentNode);
console.log(box.childNodes);
console.log(box.children);
console.log(box.nextSibling);
console.log(box.previousSibling);
console.log(box.firstChild);
console.log(box.lastChild);
节点操作,方法
appendChild()
insertBefore()
removeChild()
replaceChild()
节点层次,属性
parentNode
childNodes
children
nextSibling/previousSibling
firstChild/lastChild
var box = document.getElementById('box');
box.onclick = function () {
console.log('点击后执行');
};
box.onclick = null;
box.addEventListener('click', eventCode, false);
box.removeEventListener('click', eventCode, false);
box.attachEvent('onclick', eventCode);
box.detachEvent('onclick', eventCode);
function eventCode() {
console.log('点击后执行');
}
function addEventListener(element, type, fn) {
if (element.addEventListener) {
element.addEventListener(type, fn, false);
} else if (element.attachEvent){
element.attachEvent('on' + type,fn);
} else {
element['on' + type] = fn;
}
}
function removeEventListener(element, type, fn) {
if (element.removeEventListener) {
element.removeEventListener(type, fn, false);
} else if (element.detachEvent) {
element.detachEvent('on' + type, fn);
} else {
element['on'+type] = null;
}
}
案例
var ts = document.getElementById('ts');
document.onmousemove = function (e) {
e = e || window.event;
// ts.style.left = e.clientX -10 + 'px';
// ts.style.top = e.clientY -10 + 'px';
ts.style.left = e.pageX -10 + 'px';
ts.style.top = e.pageY -10 + 'px';
}
var box = document.getElementById('box');
box.onclick = function (e) {
// 获取盒子在页面的位置
// console.log(this.offsetLeft);
// console.log(this.offsetTop);
e = e || window.event;
// 获取鼠标在盒子中的位置
var x = getPage(e).pageX - this.offsetLeft;
var y = getPage(e).pageY - this.offsetTop;
console.log(x + ',' + y)
}
function getPage(e) {
var pageX = e.pageX || e.clientX + getScroll().scrollLeft;
var pageY = e.pageY || e.clientY + getScroll().scrollTop;
return {
pageX: pageX,
pageY: pageY
}
}