JavaScript详细学习笔记3
1. Web APIs
1.1 Web APIs和JS基础关联性
1.1.1 JS的组成
- ECMAScript:JavaScript语法 -----》JavaScript基础
- DOM:页面文档对象模型 ------》Web APIs
- BOM:浏览器对象模型 ------》Web APIs
1.1.2 JS基础阶段以及Web APIs阶段
JS基础学习 ECMAScript基础语法为后面做铺垫,Web APIs 是JS的应用,大量使用JS基础语法做交互效果
1.2 API 和 Web API
-
API:是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无序访问源码,或理解内部工作机制的细节。(会使用就行,不必纠结内部结构如何实现)
-
简单理解就是API是给程序员提供的一种工具,以便能轻松的实现想要完成的功能。
-
Web API:是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM),主要针对浏览器做交互效果
-
Web API:一般都有输入和输出(函数的传参和返回值),Web API很多都是方法(函数)
-
因为Web API很多,所以将这个阶段称为Web APIs
2. DOM
2.1 DOM简介
DOM:文档对象模型,是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口
DOM树:
- 文档:一个页面就是一个文档,DOM中使用document表示
- 元素:页面中的所有标签都是元素,DOM中使用element表示
- 节点:网页中的所有内容都是节点(属性,标签,文本,注释等),DOM中使用node表示
- DOM 把以上内容都看做是对象
2.2 获取元素
2.2.1 如何获取页面元素
- 根据ID获取
- 根据标签名获取
- 通过HTML5新增方法获取
- 特殊元素获取
// 因为文档页面从上往下加载,所以要先的有标签,所以script写到标签下面
// 1. 根据ID获取,id必须是字符串,返回一个匹配到ID的DOM element对象,若在当前document下没有找到,则返回null
var timer=document.getElementById('time');
console.log(timer); // <div id="time">2021-12-12</div>
console.log(typeof timer); // object
console.dir(timer); // div#time 打印返回的元素对象,更好的查看里面的属性和方法
// 2. 根据标签名获取 返回的是获取过来元素对象的集合,以伪数组的形式存储的 元素对象是动态的
var lis=document.getElementsByTagName('li');
console.log(lis); // HTMLCollection(2) [li, li]
console.log(lis[0]); // <li>知否,应是绿肥红瘦</li>
// 遍历
for(var i=0;i<lis.length;i++){
console.log(lis[i]);
}
// 还可以获取某个元素(父元素)内部所有指定标签名的子元素 父元素必须是单个对象(必须指明是哪一个元素对象),获取的时候不包括父元素自己
// var ol=document.getElementsByTagName('ol'); // [ol]
// console.log(ol[0].getElementsByTagName('li')); // HTMLCollection(2) [li, li]
var ol=document.getElementById('ol');
console.log(ol.getElementsByTagName('li')); // HTMLCollection(2) [li, li]
// 3. 通过HTML5新增方法获取 根据类名获取对象集合
var box=document.getElementsByClassName('box');
console.log(box); // HTMLCollection(2) [div#time.box, div.box, time: div#time.box]
// 4. document.querySelector('选择器'); 根据指定选择器返回第一个元素对象 选择器要加符号
var boxs=document.querySelector('.box');
console.log(boxs); // <div id="time" class="box">2021-12-12</div>
// 5. document.querySelectorAll('选择器'); 根据指定选择器返回所有元素对象集合
var allbox=document.querySelectorAll('.box');
console.log(allbox); // NodeList(2) [div#time.box, div.box]
// 6. 特殊元素获取
// 获取body元素
var bodys=document.body;
console.log(bodys); // <body>...</body>
console.dir(bodys); // body
// 获取html元素
var htmls=document.documentElement;
console.log(htmls);
console.dir(htmls); // html
2.3 事件基础
2.3.1 事件三要素
事件是可以被JavaScript侦测到的行为,简单理解就是触发–响应机制。
- 事件源:事件被触发的对象 谁–>按钮
- 事件类型:如何触发 什么事件 比如鼠标点击(onclick)、鼠标经过、键盘按下
- 事件处理程序:通过函数赋值方式完成
<body>
<button id="btn">唐伯虎</button>
<script>
// 1. 事件源
var btn=document.getElementById("btn");
// 2. 事件类型
// 3. 事件处理程序
btn.onclick=function(){
alert("点秋香");
}
</script>
</body>
2.3.2 执行事件过程
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值形式)
// 案例:点击div 控制台输出 我被选中了
var div=document.querySelector("div");
div.onclick=function(){
console.log("我被选中了");
}
2.3.3 常见鼠标事件
onclick | 鼠标点击左键触发 |
---|---|
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
2.4 操作元素
2.4.1 改变元素内容
-
element.innerText:从起始位置到终止位置的内容,去除html标签,同时空格和换行也会去掉(非标准)
-
element.innerHTML:起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行(W3C 标准)
<body> <button>显示当前系统时间</button> <div>某个时间</div> <p>123</p> <script> // element.innerText() var btn=document.querySelector("button"); var div=document.querySelector("div"); btn.onclick=function(){ // div.innerText='2019-6-6'; div.innerText=getTime(); } function getTime(){ // 1. 格式化日期 年月日时分秒 var data=new Date(); var year=data.getFullYear(); var month=data.getMonth(); var datas=data.getDate(); var hour=data.getHours(); var minutes=data.getMinutes(); var seconds=data.getSeconds() var arr=['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; var day=arr[data.getDay()]; return '今天是: '+year+'-'+month+'-'+datas+'- '+hour+':'+minutes+':'+seconds+' '+day; // 今天是2021年11月4日 星期六 } // 元素可以不用添加事件 var p=document.querySelector('p'); p.innerText=getTime(); </script> </body>
2.4.2 改变元素属性
// 案例:两个按钮,点击不同按钮出现不同图片
<body>
<button id="zly">赵丽颖</button>
<button id="ym">杨幂</button><br>
<img src="images/赵丽颖.jpg" alt="">
<script>
var zly=document.getElementById('zly');
var ym=document.getElementById('ym');
var img=document.querySelector('img');
ym.onclick=function(){
img.src='images/杨幂.jpg';
}
zly.onclick=function(){
img.src='images/赵丽颖.jpg';
}
</script>
</body>
2.4.3 表单元素的属性操作
<button>按钮</button>
<input type="text" value="输入内容">
<script>
// 1. 获取元素
var btn=document.querySelector('button');
var input=document.querySelector('input');
// 2. 注册事件
btn.onclick=function(){
// input.innerHTML='被点击了'; 这个是普通盒子,比如标签里面的内容
// 表单里面的值,文字内容通过value进行修改
input.value='被点击了';
// 如果想要某个表单被禁用,不能在点击,disabled
// btn.disabled=true;
this.disabled=true;
// this指向的是事件函数的调用者 btn
}
</script>
2.4.4 样式属性操作
-
element.style:行内样式操作
<style> div{ width: 200px; height: 200px; background-color: pink; } </style> <body> <div></div> <script> var div=document.querySelector('div'); div.onclick=function(){ // div.style 里面的属性采取驼峰命名法 this.style.backgroundColor='purple'; this.style.width='250px'; } </script> </body>
-
element.className:类名样式操作 会覆盖掉原来的class类名
<style> div{ width: 100px; height: 100px; background-color: pink; } .change{ background-color: purple; color: #fff; font-size: 25px; margin-top: 100px; } </style> <body> <div class="first">文本</div> <script> // 1. 使用element.style 获得修改元素样式 如果样式比较少,或者是功能简单的情况下使用 var test=document.querySelector('div'); test.onclick=function(){ // this.style.backgroundColor='purple'; // this.style.color='#fff'; // this.style.fontSize='25px'; // this.style.marginTop='25px'; // 2. 可以通过修改元素的className更改元素样式,适合于样式比较多或者功能复杂的情况 this.className='change'; // 3. 如果想要保留原来的类名, this.className='first change'; } </script> </body>
2.4.5 排他思想
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
// 获取所有按钮元素
var btns=document.getElementsByTagName('button');
// btns得到是伪数组
for(var i=0;i<btns.length;i++){
btns[i].onclick=function(){
// 先把所有按钮背景颜色去掉
for(var j=0;j<btns.length;j++){
btns[j].style.backgroundColor='';
}
// 把当前颜色改变为pink
this.style.backgroundColor='pink';
}
}
</script>
</body>
- 所有元素全部清除样式 (干掉其他人)
- 给当前元素设置样式(留下我自己)
- 注意顺序不能颠倒,首先干掉其他人,再设置自己
2.4.6 自定义属性操作
-
获取属性值
-
element.属性:获取属性值,但获取的是内置属性值(元素本身自带的属性)
-
element.getAttribute(‘属性’),主要获取自定义的属性(标准)我们程序员自定义属性
<body> <div id="demo" index="1"></div> <script> var div=document.querySelector('div'); // 1. element.属性 console.log(div.id); // demo // 2. element.getAttribute('属性') console.log(div.getAttribute('index')); // 1 </script> </body>
-
-
设置属性值
-
element.属性=‘值’:设置内置属性值
-
element.setAttribute(‘属性’,‘值’):设置自定义属性值
// 3. elemnt.属性='属性值' div.id='demo1'; console.log(div.id); // demo1 // 4. element.getAttribute('属性','值') div.setAttribute('scorll','123'); console.log(div.getAttribute('scorll')); // 123
-
-
移除属性
-
element.removeAttribute(‘属性’);
div.removeAttribute('scorll');
-
2.4.7 H5自定义属性
自定义属性的目的:是为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中
-
设置H5自定义属性
H5规定自定义属性
data-
开头作为属性名并且赋值<body> <div data-getTime='20'></div> <script> var div=document.querySelector('div'); console.log(div.getAttribute('data-getTime')); // 20 div.setAttribute('data-index',3); </script> </body>
-
获取H5自定义属性
-
兼容性获取
element.getAttribute('data-index');
-
H5新增
element.dataset.index
或者element.dataset['index']
ie 11才开始支持 -
dataset是一个集合,存放了所有data开头的自定义属性,只能获取data-开头
-
如果自定义属性里面有多个
-
链接的单词,获取的时候采用驼峰命名法<div getTime='20' data-index='2' data-list-name='andy'></div> <script> var div=document.querySelector('div'); console.log(div.getAttribute('getTime')); // 20 console.log(div.getAttribute('data-index')); console.log(div.getAttribute('data-list-name')); // H5新增 console.log(div.dataset); console.log(div.dataset.index); // 2 console.log(div.dataset.listName); // andy </script>
-
2.5 节点操作
2.5.1 为什么学习节点操作
利用节点层次关系获取元素更简单
- 利用父子兄节点关系获取元素
- 逻辑性强,但是兼容性稍差
概述:网页中的所有内容都是节点(标签、属性、注释、文本等),在DOM中,节点使用node表示
HTML DOM树的所有节点均可通过JavaScript进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除
节点至少拥有nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)三个基本属性
-
元素节点 nodeType为1
-
属性节点 nodeType为2
-
文本节点 nodeType为3(文本节点包括文字、空格、换行等)
<body> <div class="box"> <span class="erweima">x</span> </div> <script> var box=document.querySelector('.box'); console.dir(box); </script> </body>
在实际开发中,节点操作主要操作的是元素节点
2.5.2 节点层级
利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
- 父级节点:node.parentNode
- 子节点:parentNode.chileNodes (标准) 返回包含指定节点的子节点的集合,该集合为即时更新的集合
- 子节点:parentNode.children (非标准) 是一个只读属性,返回所有的子元素节点,它只返回子元素节点
<body>
<div class="box">
<span class="erweima">x</span>
</div>
<ul>
<li>1</li>
<li>2</li>
</ul>
<ol>
<li>3</li>
<li>4</li>
</ol>
<script>
// 1. 父节点
var erweima=document.querySelector('.erweima');
// var box=querySelector.querySelector('.box');
// 得到的是离元素最近的父级节点,如果找不到父节点,则返回为空
console.log(erweima.parentNode); // box
// 2. 子节点 childNodes
// DOM提供的方法(API)获取
var ul=document.querySelector('ul');
var lis=ul.querySelector('li');
// 子节点获取 chileNodes 所有的子节点,包含 元素节点,文本节点等等
console.log(ul.childNodes); // NodeList(5) [text, li, text, li, text]
console.log(ul.childNodes[0].nodeType); // 3
console.log(ul.childNodes[1].nodeType); // 1
// 得到元素节点 所以一般不提倡使用 childNodes
for(var i=0;i<ul.childNodes.length;i++){
if(ul.childNodes[i].nodeType==1){
console.log(ul.childNodes[i]);
}
}
// 3. 子节点 children
console.log(ul.children); // HTMLCollection(2) [li, li]
</script>
</body>
- 返回第一个子节点:parentNode.firstChild 找不到则返回null 包含所有节点
- 返回最后一个子节点:parentNode.lastChild 找不到则返回null 包含所有节点
- 返回第一个子元素节点:parentNode.firstElementChild (有兼容性问题,IE9以上支持)
- 返回最后一个子元素节点:parentNode.lastElementChild (有兼容性问题,IE9以上支持)
<body>
<!-- 子节点操作第一个子元素和最后一个子元素 -->
<ol>
<li>我是li1</li>
<li>我是li2</li>
<li>我是li3</li>
</ol>
<script>
var ol=document.querySelector('ol');
console.log(ol.firstChild); // #text
console.log(ol.firstElementChild); // <li>我是li1</li>
console.log(ol.lastChild); // #text
console.log(ol.lastElementChild); // <li>我是li3</li>
// 实际开发写法 既没有兼容性问题,又返回第一个元素
console.log(ol.children[0]); // // <li>我是li1</li>
// 返回最后一个元素
console.log(ol.children[ol.children.length-1]);
</script>
</body>
-
下一个兄弟节点:node.nextSibling 返回当前元素的下一个兄弟节点,找不到则返回null,也包含所有节点
-
下一个兄弟元素节点:node.nextElementSibling
-
上一个兄弟节点:node.previousSibling 返回当前元素的上一个兄弟节点,找不到则返回null,也包含所有节点
-
上一个兄弟元素节点:node.previousElementSibling
同样有兼容性问题
<body>
<div>我是div</div>
<span>我是span</span>
<script>
var div=document.querySelector('div');
console.log(div.nextSibling); // #text
console.log(div.previousSibling); // #text
console.log(div.nextElementSibling); // <span>我是span</span>
console.log(div.previousElementSibling); // null
</script>
</body>
-
自己封装一个兼容性的函数
function getNextElementSibling(element){ var el=element; while(el=el.nextSibling){ if(el.nodeType===1){ return el; } } return null; }
2.5.3 节点创建及添加
-
创建结点
document.createElement(‘tagName’):创建由tagName指定的HTML元素,因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点
-
添加节点
node.appendChild(child):将一个节点添加到指定父节点的子节点列表末尾,类似于css里面after伪元素
node.insertBefore(child,指定元素):将一个节点添加到指定子节点前面,类似于css里面before伪元素
<body>
<ul>
<li>123</li>
</ul>
<script>
// 1. 创建元素节点
var li=document.createElement('li');
// 2. 添加元素节点
var ul=document.querySelector('ul');
ul.appendChild(li); // 后面添加
var lili=document.createElement('li');
ul.insertBefore(lili,ul.children[0]); // 指定位置添加
</script>
</body>
2.5.4 节点的删除
- node.removeChild(child):从DOM中删除一个子节点,返回删除的节点
<body>
<button>删除 </button>
<ul>
<li>熊大</li>
<li>熊二</li>
<li>光头强</li>
</ul>
<script>
// 1. 获取元素
var ul=document.querySelector('ul');
var btn=document.querySelector('button');
// 2. 删除元素
// ul.removeChild(ul.children[0]);
// 3. 点击按钮一次删除
btn.onclick=function(){
if(ul.children.length==0){
this.disabled=true;
}else{
ul.removeChild(ul.children[0]);
}
}
</script>
</body>
2.5.5 复制节点(克隆节点)
node.cloneNode():返回调用该方法的节点的一个副本,也称为克隆节点/拷贝节点
注意:
- 如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
- 如果括号参数不为空或者为true,则是深拷贝,不仅克隆复制节点本身,还克隆里面的子节点
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul=document.querySelector('ul');
// 1. node.clonNode(); 浅拷贝
// var lis=ul.children[0].cloneNode();
// 2. node.cloneNode(true); 深拷贝
var lis=ul.children[0].cloneNode(true);
// 3. 添加
ul.appendChild(lis);
</script>
</body>
2.5.6 三种动态创建元素的区别(面试题)
- document.write():是直接将内容写入页面的内容流,但是文档执行完毕,则它会导致页面全部重绘。
- document.innerHTML():是将内容写入某个节点,不会导致页面重绘,创建多个页面效率更高,但不要拼接字符串,采取数组形式拼接,结构稍微复杂。
- document.createElement():创建多个元素效率稍微低一点点,但是结构更清晰。
- 不同浏览器下,innerHTML效率要比createElement高。
<body>
<button>点击</button>
<p>abc</p>
<div class="inner"></div>
<div class="create"></div>
<script>
// 1. document.write()
var btn=document.querySelector('button');
btn.onclick=function(){
document.write('<div>123</div>')
}
// 2. document.innerHTML()
var inner=document.querySelector('.inner');
// for(var i=0;i<100;i++){
// inner.innerHTML+='<a href="#">百度</a>';
// }
// 数组效率
var arr=[];
for(var i=0;i<100;i++){
arr.push('<a href="#">百度</a>');
}
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>
</body>