原生js操作dom
Web API
Web API是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)
JavaScipt由三部分构成 ECMAScript、DOM和BOM。
- BOM浏览器对象模型,提供了与浏览器的交互方法和接口;
- DOM 文档对象模型,提供了处理网页内容、结构 、样式的方法和接口;
DOM
DOM文档对象模型 又称为DOM树
DOM树 由文档、元素、节点 组成
- 文档:一个页面就是一个文档,
- 元素:文档中的所有标签都称为元素。DOM中使用Element表示
- 节点:文档中的所有内容,在文档中都是节点(标签、属性、文本注释等)DOM中使用node表示
获取元素
都以 document . 开头 例如:document.getElementById
使用
console.dir 可以打印出返回的元素对象,从而更好的查看属性和方法
getElementById (元素ID)
获取标签为Id的元素 (文档中的id值是唯一的,没有重复的id)
参数:id值,区分大小写的字符串
返回id属性值的元素节点相对应的对象
1
2
3
4
5
6
7
8
9
10
11<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>
getElementsByTagName (标签名)
注意:得到的是一个对象数组 ,如需操作元素则需要
遍历伪数组
并且伪数组不能使用数组的方法
以标签名来获取元素
参数:标签名
返回的是一个对象数组 (伪数组)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<body>
<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()获取到是
动态集合
,即:当页面增加了标签,这个集合中也就增加了元素。
getElementsByCalssName (class类名)
以class类名获取元素
参数 calss类名
返回 对应类名的元素对象集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
//getElementsByClassName根据类名获得某些元素集合
var boxs=document.getElementsByClassName("box")
console.log(boxs)
<script>
<body>
querySelector (选择器 )
可以是任意的选择器 例如:id、标签名、类名
参数: 可以是 id 、类名、标签 选择器
返回:该模式匹配的第一个元素
注意
: 需要在选择器前加符号
例如 .box 、 #nav。让querySelector 知道是什么选择器所以要加符号。 与前面介绍的不同1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<body
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
// 2. querySelector 返回指定选择器的第一个元素对象 切记 里面的选择器需要加符号 .box #nav
var firstBox = document.querySelector('.box'); //class类名
console.log(firstBox);
var nav = document.querySelector('#nav'); //id
console.log(nav);
var li = document.querySelector('li');//标签
console.log(li);
<script>
<body>
querySelectorAll (选择器)
可以是任意的选择器 例如:id、标签名、类名
参数: 可以是 id 、类名、标签 选择器
返回:该模式匹配的所有元素对象集合(伪数组 )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<body
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
// 3. querySelectorAll()返回指定选择器的所有元素对象集合
var allBox = document.querySelectorAll('.box');
console.log(allBox);
var lis = document.querySelectorAll('li');
console.log(lis);
<script>
<body>
获取特殊元素(body、html)
获取body :document.body
获取html : document.documentElement
获取元素之 节点获取
页面中所有的内容都为节点,节点使用
node
来表示
- DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
父级节点
- node.parentNode //node表示节点
- parentNode //可以返回某个节点的父节点,注意是
最近一级的父节点
- 如果指定的节点没有父节点则返回null
1 |
|
子元素节点
parentNode.children (各个浏览器都支持) (不包含 元素节点,文本节点等)
parentNode.firstElementChild (获取第一个元素节点) 具有兼容问题 ie9才支持
parentNode.lastElementChild (获取最后一个子元素节点) 具有兼容问题 ie9才支持
parentNode.children[0] (没有兼容性问题,并且返回第一个子元素)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<script>
// 2. children 获取所有的子元素节点(不包括文本节点等)也是我们实际开发常用的
console.log(ul.children);
//2.firstElementChild 获取第一个子元素节点 ie9以上才支持
console.log(ul.firstElementChild)
//3.lastElementChild 获取最后一个子元素节点 ie9以上才支持
console.log(ul.lastElementChild)
//4.children[0] 开发中经常使用 没有兼容问题并且返回第一个子元素
console.log(ul.children[0])
console.log(ul.children[children.length-1])
</script>
兄弟节点
node.nexElementSibling //返回当前元素下一个兄弟元素节点,找不到则返回null
node.previousElementSibling // 返回当前元素上一个兄弟节点,找不到则返回null
两种方法都有兼容性的问题,IE9以上支持
1
2
3
4
5
6
7
8
9
10<div>我是div</div>
<span>我是span</span>
<script>
var div = document.querySelector('div');
var span=documnet.querySelector("span")
// 1. nextElementSibling 得到下一个兄弟元素节点
console.log(div.nextElementSibling);
// 2.nextElementSibling 得到上一个兄弟元素节点
console.log(span.previousElementSibling);
</script>问:解决兼容性问题
答:自己封装一个兼容性的函数
1
2
3
4
5
6
7
8
9function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
事件处理
javaScript程序中采用的是异步处理事件模型,事件处理分三部分。
事件源 (具体作用在哪 个元素或标签上)
事件类型 (指的是 例如:鼠标的点击,双击,经过,键盘的按下的键)
处理程序 ( 指的是 事件触发后浏览器调用对应的处理程序(以函数的形式),也称为事件处理函数)
1
2
3
4
5
6
7
8
9
10
11
12
13<body>
<div> 事件处理 <div>
<script>
//1.获取事件源
var div=document.querySelector("div")
// 2.绑定事件 注册事件
div.onclick
//3.添加事件处理程序
div.onclick=function(){
console.log("我")
}
<script>
<body>
注册事件
注册事件有三种方法
使用HTML标签属性注册(例如 Vue的事件注册)
使用传统的DOM对象注册 (onclick) 具有唯一性
注意:使用这种方式注册 一个事件源只能注册一个,如注册多个,后面的覆盖前面的注册事件
使用
addEventListene
r(type,listener,useCapture)的方法监听注册
方式 (即可添加多个,也可以取消事件)- type :事件类型 , 例如:click、mouseover
注意
这是里不需要带on - listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:可选参数,是一个布尔值,默认是false 。(false为捕获阶段,true为冒泡阶段)
注意:addEventListener() 方法 不支持低版本的IE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<body>
<div onClick=show()> 注册事件的三种方法 <div>
<script>
//1.使用HTML属性注册
function show(){
alert("div被点击了")
}
//2.使用javaScipt的DOM注册事件
var div=document.querySelector("div")
//注意 事件类型以 on开头 后面对应的事件名为小写
div.onclick=function(){
alert("DOM注册点击div")
}
//3.使用addEventListener()方法注册事件
var div=document.querySelector("div")
//向div添加事件
div.addEventListener('click',()=>{
alert("Div 注册点击事件")
})
//移除div事件
div.removeEventListener("click",()=>{
alert("移除div事件")
})
<script>
<body>- type :事件类型 , 例如:click、mouseover
删除事件(解绑事件)
- 移除传统的注册方式(DOM 对象的方法)
- div.onclick=null;
- 移除监听事件的方式 (使用匿名函数 ,无法移除 )
- div.removeEventListener (type,listener,useCapture);
1 |
|
鼠标事件
- 鼠标事件的执行顺序
mousedown->mouseup->click->mousedown->mouseup->click->dbclick
鼠标事件 | 描述 |
---|---|
click | 鼠标点击左键并释放时触发 |
dbclick | 双击鼠标左键时触发 |
mousedown | 按下鼠标按键时触发 |
mouseup | 释放鼠标按键时触发 |
mouseover |
当鼠标经过时触发 具有事件冒泡 |
mouseout |
当鼠标离开时触发 具有事件冒泡 |
mouseenter |
当鼠标经过时触发 不具有事件冒泡 |
mouseleave |
当鼠标经过时触发 不具有事件冒泡 |
mousemove | 当移动鼠标时触发 |
contextmenu | 禁止鼠标右键菜单 |
selectstart | 禁止鼠标选中文字 |
只有在同一个元素上相继触发 mouseover 和 mouseup事件 才会触发click事件
只有触发再两次click事件,才会触发一次dbclick事件
mouseenter与mouseove的区别
- mouseenter经常与mouseleave搭配使用
1
2
3
4
5
6
7
8
9
10
11
12//1.mouseenter 鼠标经过 不具有事件冒泡,不会传递给son点击事件
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
father.addEventListener('mouseenter', function() {
console.log(11);
})
</script>禁止鼠标右键菜单
1
2
3
4//1.contextmenu 禁止鼠标右键菜单
documnet.addEventListener("contextmenu",function(e){
e.preventDefault(); // 阻止事件的默认跳转行为
})禁止鼠标选中文字
1
2
3
4//2.selectstart 禁止鼠标选中文字
documnet.addEventListener("selectstart",function(e){
e.preventDefault(); //阻止事件的默认跳转行为
})
焦点事件
mous焦点事件 | 描述 |
---|---|
blur | 元素失去焦点时触发,不会冒泡 |
focus | 元素获得焦点时触发,不会冒泡 |
键盘事件
一般键盘事件使用在 输入框的标签中
当按下字符键的
执行顺序
(按下字符键 触发三次事件
)keydown->keypress->keyup 其中 keydown和keypress在文件框发生变化之前触发,然后是keyup事件则是在文件框发生变化之后触发
当按下非字符键的
执行顺序
(按下非字符, 触发二次事件
)keydown->keyup 其中首先触发 keydown,最后触发keyup.
注意
:keydown和keypress在文本框里面特点:先执行事件的处理程序 在将文字落入到文本框中keyup
在文本框里面的特点:先将文字落入到文本框中在执行事件的处理程序keypress
不识别功能键,但是keyCode
属性能区分大小写,返回不同的ASCII
值onkeydown
和onkeyup
,不区分字母大小写,onkeypress
区分字母大小字
键盘事件 | 描述 |
---|---|
keydown | 按下键盘上的任意键触发;按住不放,重复触发 |
keypress | 按下键盘上的字符键触发;按住不放,重复触发,不识别功能键,如 箭头,ctrl,shift 等 |
keyup | 释放键盘上的键时触发 |
e.keyCode | 当用户按下按键时获取按键 ASCII 编码 |
e.key | 获取当用户按下按键时的 名称 |
1 |
|
滚动条事件
当出现滚动条时,向下滚动页面时,上面被隐藏掉的高度,被称为页面被卷去的部分,此时滚动条在滚动时会触发 scroll事件
1 |
|
表单事件
change
事件 当表单的值 发生改变时触发
事件对象
在触发DOM上的某个事件时会产生一个事件对象event ,这个对象中包含着所有与事件有关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息。
事件触发时系统会产生一个事件对象,并且系统会以实参的形式传给事件处理函数
在事件处理程序中声明一个形参用来接收事件参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//1. 方法一
eventTarget.onclick=function(event){
//这个event就是事件对象,我们还喜欢的写成 e 或者 evt
}
// 2. 方法二
eventTarget.addEventListener("click",function(event){
//这个event就是事件对象,我们还喜欢的写成 e 或者 evt/这个
})
//3.方法三
eventTarget.addEventListener("click",fn)
function(event){
//这个event就是事件对象,我们喜欢写成e或者evt
}
事件对象的属性和方法
事件对象的属性和方法 | 说明 |
---|---|
e.target | 返回 触发 事件的对象 标准 |
e.srcElement | 返回触发 事件的对象 非标准 ie6-8 |
e.type | 返回事件的类型 比如 click mouseover 不带 on |
e.canceIBubble | 该属性阻止冒泡 非标准 ie6-8 使用 |
e.returnValue | 该属性 阻止默认事件(默认行为)非标准 ie6-8 使用 比如不让链接跳转 |
e.preventDefault() | 该方法阻止默认事件(默认行为)标准 比如不让链接跳转 |
e.stopPropagation() | 标准的阻止事件冒泡 |
事件对象的 this与e.target的区别
this 指向的是事件绑定的元素
e.target 指向的是事件触发元素
别忘了e.
通常情况下
e.target
和this
的指向是一致的但是有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行)
这时候 this 指向的是元素,因为this使终指向的是事件绑定的元素
target 指向的是子元素 ,因为target使终指向的是事件触发的元素
1 |
|
鼠标的事件对象
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的 X 坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的 Y 坐标 |
e.pageX | 返回鼠标相对于文档页面的 X 坐标 IE9+ 支持 |
e.pageY | 返回鼠标相对于文档页面的 Y 坐标 IE9+ 支持 |
e.screenX | 返回鼠标相对于电脑屏幕的 X 坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y 坐标 |
1 |
|
操作元素
修改元素内容
个人推荐: innerHTML 使用多
Element.innerText
只显示纯文本,去除html标签,同时去除了空格和换行
Element.innerHTML
显示指定的元素的全部内容,包括HTML标签,同时保留空格和换行
innerText与innerHTML的区别
- 使用innerText
获取内容
不识别
HTML标签, 空格与换行 - 使用innerText
设置内容
不识别
HTML标签 - 使用innerHTML获取内容
识别
全部内容包括 HTML标签 ,会保留空格和换行 - 使用innerHTML设置内容
识别
可设置HTML标签
- 使用innerText
1 |
|
属性的操作
this
指向的是事件函数的调用者
- 普通元素的属性操作
- 表单元素的属性操作
获取属性的值
元素对象.属性名
设置属性的值
元素对象.属性名=值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<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>
样式属性操作
通过 js 修改元素大小,颜色,位置等模式
常用方式
Element.style.样式=值 //行内样式操作 修改行内样式 权重较高
Element.className=“类名” //类名样式操作 覆盖原先的类名
- Element.className=“ ” //值为空或null 可使元素的类名置空
Element.classList.add (“类名”) // 添加类名操作 可添加多个
不会覆盖原有的类名
- Element.classList.remove( “ 移除类名”) // 移除类名操作
可移除多个类名
- Element.classList.toggle( “切换类名 ”) //切换类名 无则添加,有则移除
- Element.calssList.contains( “类名” ) //是否包含此类名,
返回布尔值
判断是否为存在
calssName是保留字,因此使用calssName来操作元素类名属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<body>
<div></div>
<script>
// 1. 获取元素
var div = document.querySelector('div');
// 2. 注册事件 处理程序
div.onclick = function() {
// div.style里面的属性 采取驼峰命名法 js中对大小写敏感
this.style.backgroundColor = 'purple';
//别忘了加 单位 px
this.style.width = '250px';
// 2. 我们可以通过 修改元素的className更改元素的样式 适合于样式较多或者功能复杂的情况
// 3. 如果想要保留原先的类名,我们可以这么做 多类名选择器
// this.className = 'change';
this.className = 'first change';
}
</script>
</body>- Element.classList.remove( “ 移除类名”) // 移除类名操作
取消 a 标签的默认跳转
方法一: 在处理程序内的最后 添加
return false ;
方法二: 在 a标签中加
javascript:;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21javascript复制代码//方法一: 事件处理程序中最后设置 return false;
<body>
<a id="link" href="https://www.baidu.com">点击</a>
//方式2:设置a标签的href属性值为:javascript:
<a href="javascript:;">点击2</a>
<script>
var link = document.getElementById('link');
link.onclick = function(){
alert('你好');
// 方式1:取消a点击后的默认跳转行为 return false;
return false;
};
</script>
<body>
//方式2:设置a标签的href属性值为:javascript:;
<a href="javascript:;">点击2</a>
//备注:
// 给a标签的herf值设置javascript: ,表示将来点击a时,会阻止默认跳转行为,并且仅仅会执行js代码
全选案例:全选
1 |
|
自定义属性操作
为什么需要自定义属性:用于在页面中存储数据而不用在数据库中存储
获取属性值
- Element.属性 (内置属性通 点的方式 获取元素属性)
- Element.getAttribute(“属性”) (一般用于 自定义属性)
兼容性获取
1 |
|
设置属性值
- Element.属性= “值” (内置属性)
- Element.setAttribute( “属性”,”值“ ); //一般用于自定义属性
1 |
|
移除属性值
- Element.removeAttribute(“属性”)
1 |
|
获取H5自定义属性
只能获取以 data开头 的自定义属性
Element.dataset.index 或者 Element.dataset[“index”] ie11才支持
使用 Element.dataset.属性 获得的是一个以 data- 开头的自定义属性集合
设置H5 自定义属性
H5中规定 自定义属性要 以 data-开头做为属性名并且赋值。
在标签中设置
<div data-index="1"> </div>
使用 js设置
Element.setAttribute(“data-index”,2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
var div = document.querySelector('div');
// console.log(div.getTime);
console.log(div.getAttribute('getTime'));
div.setAttribute('data-time', 20);
console.log(div.getAttribute('data-index'));
console.log(div.getAttribute('data-list-name'));
// h5新增的获取自定义属性的方法 它只能获取data-开头的
// dataset 是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset);
console.log(div.dataset.index);
console.log(div.dataset['index']);
// 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
console.log(div.dataset.listName);
console.log(div.dataset['listName']);
</script>
Tab栏 案例 :tab栏
1 |
|
节点操作
node 表示父级 child 表示子级
创建节点
- document.createElement(“标签”)
- 动态创建元素 创建之后需要添加
添加节点
node.appendchild(child ) //node表示父级 child表示子级
- 将节点添加到node表示的父节点的子节点列表的
末尾
,类似数组的方法push
- 将节点添加到node表示的父节点的子节点列表的
node.insertBefore( child,指定节点的位置 )
- 将节点添加到node表示的父节点的指定子节点的~`前面`,类似于css里面的before伪元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<body>
<ul>
<li>123</li>
</ul>
<script>
// 1. 创建节点元素节点
var li = document.createElement('li');
// 2. 添加节点 node.appendChild(child) node 父级 child 是子级 后面追加元素
var ul = document.querySelector('ul');
ul.appendChild(li);
// 3. 添加节点 node.insertBefore(child, 指定元素);
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
// 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素
</script>
</body>
删除节点
node.removeChild( child ) 方法 在父级节点删除一个子节点,返回删除的节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<body>
<button>删除</button>
<ul>
<li>熊大</li>
<li>熊二</li>
<li>光头强</li>
</ul>
<script>
// 1.获取元素
var ul = document.querySelector('ul');
var btn = document.querySelector('button');
// 2. 删除元素 node.removeChild(child)
// 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>
复制(克隆)节点
node.cloneNode() //返回调用 该方法的节点的一个副本,也称为克隆节点/拷贝节点
如果括号参数为空或者为 false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
如果括号参数为true,则是深度拷贝,会复制节点本身以及里面所有的子节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14<body>
<ul>
<li>1111</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
// 1. node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
// 2. node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容
var lili = ul.children[0].cloneNode(true);
ul.appendChild(lili);
</script>
</body>
DOM的核心总结
DOM操作,我们主要针对于元素的操作。主要有创建,添加,删除,改,查。
创建元素的三种方式
- document.write()
- Element.innerHTML= 值
- document.createElement()
innerHTML数组方式(效率高)
1 |
|
添加
- appendChild //在父节点的末尾添加节点
- insertBefore //可以指定子节点的添加位置
删除
- removeChild
改
- 主要修改DOM元素的属性,DOM元素的内容,属性,表单的值等。
- 修改元素属性: src、href、title等
- 修改元素的普通内容: innerHMTL、innerText
- 修改表单元素:value、type、disabled等
- 修改元素的模式,style、className
查
- DOM提供的API:getElementById,getElementByTagName 古老用法不太推荐使用
- H5提供的新方法:querySelector,querySelectorAll 推荐
- 利用节点操作获取元素:父(parentNode)、子(children)、兄弟(previousElementSibling、nextElementSibling) 推荐
操作自定义属性
- 主要操作自定义属性
- setAttribute: 设置自定义属性
- getAttribute:获取自定义属性
- removeAttribute:移除属性