DOM Document Object Model(文档对象模型)
如何获取页面元素
1.根据ID获取
getElementById(ID);
<body> <div id="card"> 黎明的那道光 </div> <script> document.getElementById(card); </script> </body>
console.dir()打印我们返回的元素对象,更好的查看里面的属性和方法
2.根据标签名获取
使用document.getElementsByTagName()可以返回带有指定标签名的集合
<ul> <li>有一种悲伤</li> <li>北方的冬夜是否暖过上海的夏天</li> <li>不找了</li> <li>世间美好与你环环相扣</li> </ul> <script> //获取的是元素对象的集合,以伪数组的形式存储 var lis=document.getElementsByTagName('li'); console.log(lis);
console.log(lis[0]);//获取第一个li </script>
还可以获取某个元素(父元素)内部所有指定标签名的子元素
element.getElementsByTagName('标签名');
3.通过HTML5新增的方法获取
document.getElementsByClassName('类名')//根据类名返回元素对象集合
querySelector()返回指定选择器的第一个元素对象,注意里面的选择器需要加符号
querySelectorAll()返回指定选择器的所有元素对象
<div class="box">123</div> <div class="box">456</div> <script> var boxs=document.getElementsByClassName('box'); console.log(boxs); //2.querySelector()返回指定选择器的第一个元素对象,注意里面的选择器需要加符号 //3.querySelectorAll()返回指定选择器的所有元素对象 var num=document.querySelector('.box'); console.log(num); </script>
4.特殊元素获取(body 或html标签)
获取body document.body;
获取html document.documentElement;
5.利用节点的层级关系获取元素
事件三要素:
事件源,事件类型,事件处理程序
<button id="btn">唐伯虎</button> <script> //实现点击按钮弹出对话框 //1.事件源 事件被触发的对象 在此处为按钮 var btn=document.getElementById('btn'); //2.事件类型 如何触发这个时间 是鼠标点击 还是鼠标经过等等 btn.onclick=function(){//实现了鼠标点击时弹出对话框点秋香 alert('点秋香'); } </script>
执行事件的步骤
1.获取事件源
2.注册事件(绑定事件)
3.添加事件处理程序(采取函数赋值程序)
js的DOM操作可以修改网页结构的内容,结构和样式,可以利用DOM操作元素来修改元素里面的内容,属性等
改变元素内容:
element.innerText 从起始位置到终止位置的内容,但他去除html的标签。同时空格和换行也会去掉
element.innerHTML 起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
<body> <button>显示当前系统时间</button> <div>时间</div> <script> //实现点击按钮div里的文字变成当前时间 //1.获取元素 var btn=document.querySelector('button'); var div=document.querySelector('div'); //2.注册事件 btn.onclick= function() { div.innerText=getDate();//若这句不在函数内,则刷新之后直接出时间,不用点击按钮
function getDate() { var date=new Date(); var year=date.getFullYear(); var month=date.getMonth()+1; var dates=date.getDate(); var day=date.getDay(); var arr=['星期日','星期一','星期二','星期三','星期三','星期四','星期五','星期六']; return '今天是'+year+'年'+month+'月'+dates+'日'+arr[day]; } </script> </body>
innerText (非标准)与innerHTML(w3c标准,更为常用)的区别
①前者不识别html的标签,后者识别
<div></div> <script> var div=document.querySelector('div'); div.innerText='<strong>今天是:</strong>2019';//输出为<strong>今天是:</strong>2019 div.innerHTML='<strong>今天是:</strong>2019';//按理想效果输出 </script>
②这两个属性都是可读写的,可以获取标签里面的内容
<p> 我是文字 <span>345</span> </p> <script> var p=document.querySelector('p'); console.log(p.innerText);//我是文字 345 console.log(p.innerHTML);/*我是文字 <span>345</span>*/ </script>
修改元素属性
案例(实现点击不同按钮时显示不同的图片)
<button id="tp1">图片1</button> <button id="tp2">图片2</button> <img src="images/图片1.jpg" title="图片1"> <script> var tp1=document.getElementById('tp1'); var tp2=document.getElementById('tp2'); var img=document.querySelector('img'); tp1.onclick=function(){ img.src='images/图片1.jpg'; img.title='图片1'; } tp2.onclick=function(){ img.src='images/图片2.jpg'; img.title='图片2'; } </script>
案例(实现不同时间显示不同图片和文字)
<img src="images/图片1.jpg"> <div>上午</div> <script> //实现不同时间显示不同的图片和文字 var img=document.querySelector('img'); var div=document.querySelector('div'); var date=new Date(); var hour=date.getHours(); if(hour>12){ img.src='images/图片2.jpg'; div.innerHTML='下午'; } else{ img.src='images/图片1.jpg'; div.innerHTML='上午'; } </script>
表单元素的属性操作(.innerHTML可以对普通盒子如div里的内容进行修改,但对表单里的内容则不能用.innerHTML)
利用DOM可以操作如下表单的属性
type,value,checked,selected,disabled
<button>按钮</button> <input type="text" value="输入内容"> <script> var btd=document.querySelector('button'); var input=document.querySelector('input'); btd.onclick=function(){ input.value='被点击了'; btd.disabled=true;//实现点击按钮后按钮被禁用
//或者this.disabled=true;this指向的是事件函数的调用者
} </script>
案例(仿京东显示密码,点击按钮将密码框切换为文本框,并可以查看密码明文)
<style> .box{ position:relative; 400px; border-bottom:solid #ccc 1px; margin:100px auto; } .box input{ 370px; height:30px; border:0; outline: none;/*不会的地方*/ } .box img{ 24px; position:absolute; right: 10px; bottom:5px; } </style> </head> <body> <div class="box"> <label for=""> <img src="images/图片1.jpg" id="eye"> </label> <input type="password" name="" id="pwd"> </div> <script> var eye=document.getElementById('eye'); var pwd=document.getElementById('pwd'); var flag=0; eye.onclick=function(){ if(flag==0){ pwd.type='text'; eye.src='images/图片2.jpg'; flag=1; } else{ pwd.type='password'; eye.src='images/图片1.jpg'; flag=0; } } </script>
样式属性操作
通过js来修改元素的大小,颜色,位置等样式。
element.style (里面的属性采取驼峰命名法)行内样式操作
//js修改style样式操作,产生的是行内样式,css权重比较高
element.className 类名样式操作
循环精灵图
①首先精灵图图片排列是有规律的
②核心思路:利用for循环,修改精灵图片的背景位置background-position
显示隐藏文本框内容
//鼠标点击时文本框默认内容消失,未点击则继续显示
首先表单需要两个新的事物 获得焦点onfocus 失去焦点onblur
<body> <input type="text" value="手机"> <script> var text=document.querySelector('input'); text.onfocus = function() { if(text.value==='手机'){ text.value= ''; } text.style.color='#333'; } text.onblur = function() { if(text.value=== ''){ text.value='手机'; } text.style.color='#999'; } </script> </body>
使用className修改样式属性
具体操作是先在style中写一个类的样式,然后当对目标进行某项操作想要实现这个样式时,可用classNane使得目标具有这个类样式所设定的属性,适合于功能较多或者样式复杂的情况,注意className会更改元素的类名,覆盖原来的类名
如果想要保留原来的类名。、,假设原来的类名是first,则只需代码中//位置修改为this.className='first chance'
<style> div{ background-color: pink; 200px; height:200px; } .chance{ background-color: purple; color:white; font-size: 15px; } </style> </head> <body> <div>文本</div> <script> var text=document.querySelector('div'); text.onclick= function() { this.className='chance';// } </script> </body>
排他思想
先设置其他元素的样式,才来设置自己的
如果有同一组元素,希望进行某种操作时其中的一个有某种样式,其余的无,则可以运用排他思想,主要通过对伪数组进行for循环
比如样例(多个按钮实现被点击按钮变成粉红色)
<button>按钮</button> <button>按钮</button> <button>按钮</button> <button>按钮</button> <button>按钮</button> <script> var btn=document.getElementsByTagName('button'); for(var i=0;i<btn.length;i++){ btn[i].onclick=function() { for(var i=0;i<btn.length;i++){ btn[i].style.backgroundColor= ''; } this.style.backgroundColor= 'pink'; } } </script>
自定义属性
自定义属性的目的:是为了保存并使用数据,有些数据可以保存到页面而不用保存到数据库中
有些自定义属性容易引起歧义,不好分辨是自定义属性还是内置属性,这一问题再H5中得以解决。H5规定自定义属性以data-开头并且赋值
如果自定义属性里面有多个用-链接的单词,我们获取时采取驼峰命名法比如自定义属性data-list-name=" ",获取时为element.dataset.listName
获取属性值
1.element.属性(获取内置属性,元素自带的属性如id,class之类)
2.elememt.Attribute(‘属性')(主要获取自定义属性,程序员自己定义的属性)已有的属性值可能无法满足需求,这时可自定义属性
3.element.dataset.属性(此时属性里不用含data-)或者element.dataset['属性'](此时属性里不用含data-) H5新增获取自定义属性值的方法 ie11
设置元素属性值
element.属性='值',修改class的属性值时,是element.className='值'。(设置内置属性值)
element.setAttribute('属性','值')(主要针对自定义属性)
移除属性
element.removeAttribute('属性');
节点
网页中的所有内容都是节点(标签,属性,文本,注释等),在DOM中,节点使用node来表示
HTML DOM树中的所有节点都可以通过JavaScript进行访问,所有HTML元素(节点)都可以被修改,也可以创建或删除。一般的,节点要至少拥有nodeType(节点类型),nodeName(节点名称),nodeValue(节点值),
元素节点 nodeType 为1
属性节点 nodeType 为2
文本节点 nodeType 为3(文本节点包括文字 空格 换行等)
实际开发中,节点操作主要是元素节点
1.父节点node.parentNode.如果指定的节点没有父节点则返回NULL
2.子节点parentNode.childNodes(得到所有的子节点,包括元素节点,文本节点等等)如果只想获得里面的元素节点,可以通过for循环来判断,如果其nodeType为1则是元素节点,然后进行操作
parentNode.children(非标准)返回所有的子元素节点,虽然是非标准,但得到了各个浏览器的支持,可以放心使用。
3.节点操作中第一个子元素和最后一个子元素
parentNode.firstChild获取的是第一个子节点,包括文本节点
parentNode.lastChild获取最后一个子节点,同样包括文本节点
parentNode.firstElementChild获取第一个子元素节点
parentNode.lastElementChild获取最后一个子元素节点//这两个有兼容问题。IE9及以上才可以使用
实际开发中常用的是用伪数组来获取
paerentNode.children[数组索引]。
4.兄弟节点
node.nextSibling获取下一个节点,包含元素节点和文本节点。
node.previousSibling获取上一个节点,包含元素节点和文本节点
想要通过兄弟节点只获得元素节点
node.nextElementSibling
node.previousElementSibling//这两个也是有兼容性问题IE9及以上
可以自己封装一个兼容性的函数
5.节点操作之创建和添加节点
想要页面中添加一个元素,有两步,先要创建元素,然后再添加元素。
document.creatElement('tagName');
这个元素原本是不存在的,是根据我们的需求动态生成的,所以又称为动态创建元素节点
只创建节点是不够的,还需要与添加节点同时使用,告诉计算机将节点添加到哪里
添加节点
node.appendChild(child),此方法将一个节点添加到指定父节点的子节点列表末尾,类似于css里面的after伪元素。
//实现向ul里面添加li
<ul></ul>
<script>
var li =document.createElement('li');
var ul =document.querySelector('ul');
ul.appendChild(li);
</script>
node.insertBefore(child,指定元素)将一个节点添加到指定子节点的前面,类似于css里面的before伪元素
<ul>
<li>123</li>
</ul>
<script>
var lili =document.createElement('li');
var ul =document.querySelector('ul');
ul.insertBefore(lili,ul.children[0]);
</script>
简单版发布留言的案例
核心思路:点击发布之后,动态创建一个li,添加到ul里面,
创建li的同时,将文本域里面的值通过li.innerHTML赋值给li
如果需要新的留言在后面显示,使用appendChild如果希望在前面显示,使用innsertBefore
<textarea name="" id="" cols="30" rows="10"></textarea> <button>发布</button> <ul> </ul> <scriPt> var text=document.querySelector('textarea'); var btn=document.querySelector('button'); var ul=document.querySelector('ul'); btn.onclick = function() { if(text.value==''){ alert('您没有输入内容'); return false; } else{ var li=document.createElement('li'); li.innerHTML=text.value; ul.appendChild(li); } } </scriPt>
删除节点
node.removeChild(child)
删除一个节点的例子
<body> <ul> <li>熊大</li> <li>熊二</li> <li>光头强</li> </ul> <script> var ul=document.querySelector('ul'); ul.removeChild(ul.children[0]); </script> </body>
点击一次按钮删除一个节点的例子
点击一次按钮删除一个节点,当无节点时,按钮变为禁用按钮
<button>删除</button> <ul> <li>熊大</li> <li>熊二</li> <li>光头强</li> </ul> <script> var ul=document.querySelector('ul'); var btn=document.querySelector('button'); btn.onclick=function() { if(ul.children.length==0){ this.disabled='true'; } else ul.removeChild(ul.children[0]); } </script>
复制节点
node.cloneNode()返回调用该函数节点的一个副本,也成为复制节点或拷贝节点。
如果括号里参数为空或者false,则为浅拷贝,只克隆复制节点本身,不克隆里面的子节点
node.cloneNode(true)深拷贝
<body> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> <script> var ul=document.querySelector('ul'); var lili=ul.children[0].cloneNode(true); ul.appendChild(lili); </script> </body>
三种动态创建元素的区别
document.write()(不常用,了解即可)直接将内容写入页面的内容流,但是文档流执行完毕,它会导致页面全部重绘。
element.innerHTML.创建多个元素效率更高(不要用拼接字符串,采取数组形式拼接),结构稍微复杂
createElement()创建多个元素效率稍微低一点点,但是结构更清晰
事件高级
注册事件的两种方式
1.传统方式(前面一直用的方式)
①利用on开头的事件onclick
②注册事件的唯一性
同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面的处理函数
为了解决此问题,下面的注册方式应运而生
2.方法监听注册方式
①addEventListener()它是一个方法,IE9以前的版本不支持,可使用attachEvent()(非标准,不常用)注册事件
②同一个元素同一个事件可以添加多个监听器
③按注册顺序依次执行
④如何使用
eventTarget.addEventListener(type,Listener[,userCapture]);
此方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会触发事件处理函数,
type :事件类型字符串,如click,mouseover,注意这里不带on
listener : 事件处理函数,事件发生时,会调用该监听函数
useCapture : 可选参数,是一个布尔值,默认是false
实现点击按钮弹出内容
<body> <button>按钮</button> <script> var btn=document.querySelector('button'); //addEventListener里面的事件类型是字符串,而且不带on btn.addEventListener('click',function() { alert('hi'); }) btn.addEventListener('click',function() { alert('hello'); }) //会先弹出hi,然后弹出hello </script> </body>
封装函数解决兼容性问题
删除事件(解绑事件)
1.传统注册方式
eventTarget.onclick=null;
2.方法监听注册方式
eventTarget.removeEventListener(type,Listener[,userCapture]);
<div>12</div> <div>22</div> <script> //普通点击得删除事件 var divs=document.querySelectorAll('div'); divs[0].onclick=function() { alert('33'); divs[0].onclick=null; } divs[1].addEventListener('click',fn); //因为删除时间需要知道函数名,所以此处不再用匿名函数 function fn() { alert('22'); divs[1].removeEventListener('click',fn); } </script>
DOM事件流
事件流描述的是从页面中接受事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
DOM事件流分为三个阶段
1,捕获阶段
2.当前目标阶段
3.冒泡阶段
JS只能执行捕获或者冒泡的其中一个阶段
onclick 和 attackEvent 只能得到冒泡阶段
addEventListener(type,listener[,useCapture])第三个参数如果是true,则表示在事件捕获阶段调用事件处理程序,如果是false(不写则默认false),表示在事件冒泡阶段调用事件处理程序
实际开发中更关注的是事件冒泡。很少关注事件捕获
有些事件是没有冒泡的,如onblur,onfocus,onmouseenter,onmouseleave;
<div class="father"> <div class="son">son</div> </div> <script> var son=document.querySelector('.son'); son.addEventListener('click',function() { alert('22'); },true) var father=document.querySelector('.father'); father.addEventListener('click',function() { alert('33'); },true) </script>
事件对象
官方解释:event对象代表事件的状态,比如键盘按键的状态,鼠标的位置,鼠标按钮的状态
简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,他有很多的属性和方法<body>
<div></div> <script> var div=document.querySelector('div'); div.onclick=function(event) {//小括号里面写入e或event,监听函数同 console.log(event); } //事件对象只有有了事件才会存在,是系统自动创建的,不需要我们传递参数, //事件对象我们可以自己命名,但比较常用e,event,evt //事件对象存在兼容性问题,ie678通过windows.event
//event是形参,不需要传递实参进去
//兼容性问题解决 e=e||windows.event
</script> </body>
<div> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> </div> <script> var ul=document.querySelector('ul'); ul.onclick=function(e) { //this指向的是绑定的对象 console.log(this);//返回ul //e.target指向的是我们点击的对象 console.log(e.target);//返回li(如果点击的是li) } </script>
阻止事件冒泡
利用事件对象里面的stopPropagation()方法
示例
<div class="father"> <div class="son">son</div> </div> <script> var son = document.querySelector('.son'); son.addEventListener('click',function(e) { alert('22'); e.stopPropagation();//点击son之后终止son冒泡 },false); var father=document.querySelector('.father'); father.addEventListener('click',function() { alert('33'); },false); </script>
事件委托(代理,委派)
事件冒泡本身的特性,会带来坏处,也会带来好处,需要我们灵活应用
事件委托原理(记住)
不是给每个子节点单独设置事件监听器,而是事件监听器设置在其父结点上,然后利用冒泡原理影响设置每个子节点
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul> <script> //为li添加点击效果 //事件委托的核心原理,给父节点添加监听器,运用事件冒泡影响每一个子节点 var ul=document.querySelector('ul'); ul.addEventListener('click',function(e) { e.target.style.backgroundColor="pink"; }) </script>
禁止鼠标右键菜单
<body> 文字 <script> document.addEventListener('contextmenu',function(e){ e.preventDefault(); }) </script> </body>
禁止鼠标选中
<body> 文字 <script> document.addEventListener('selectstart',function(e){ e.preventDefault(); }) </script> </body>
常用的鼠标事件
event对象代表事件的状态,跟事件相关的一系列信息的集合,现阶段我们主要是用鼠标事件对象MouseEvent和键盘事件对象KeybordEvent
鼠标事件对象
<script> document.addEventListener('click',function(e) { console.log(e.clientX); console.log(e.clientY); console.log('---------'); console.log(e.pageX); console.log(e.pageY); }) </script>
案例:设置图片一直跟随鼠标
<img src="1.jpg" alt="图片"> <script> var pic=document.querySelector('img'); document.addEventListener('mousemove',function(e) {//document.对文档出发 //mousemove只要鼠标移动1像素,就会触发这个事情。 var x =e.pageX; var y =e.pageY; //千万不要忘记给left和top添加px单位!! pic.style.left=x+'px'; pic.style.top=y+'px';
//如果想让图片位于鼠标居中位置,这里分别减去对应图片一半的大小即可 }); </script>
常用键盘事件
这里仍要注意使用addEventListener时,不带on
三个事件的执行顺序,keydown-keypress-keyup
keyCode判断用户按下了哪个键,可以得到按下键的相应的ascii值
<script> document.addEventListener('keyup',function(e) { console.log(e.keyCode); //keyup和keydown事件不区分大小写,a与A得到的都是65
//keypress区分字母的大小写
}); </script>
blinbling完美结束