DOM

所谓DOM是给文档中的每一个标签都对应的创建一个对象。

在JS中默认就会为页面的所有的标签创建一个对应的对象模型。我们可以通过对应的API获取这些对象模型,通过这些对象模型操作页面的标签。

通过JS操作DOM对象

DOM对象模型的最顶层是一个对象:document。表示整个文档。这个对象是内置的,不需要你创建,直接可以使用。 就好像我们之前使用的一个API document.getElementById(id);

tips: JS是基于对象的语言。 

[1]获取页面中的标签对应的DOM对象。

JS给我们提供了几个API:(一些提供的方法,这些方法都是document对象的方法)

通过元素的id直接获取一个指定的标签的DOM对象document.getElementById(id);

参数ID就是要获取的元素的ID

案例:

        var usernameDom = document.getElementById("username");
l(usernameDom);
alert(usernameDom);

浏览器控制台输出的效果:

浏览器格式化之后得到的效果。也就是对象的toString。

alert的效果:

上面的toString是[object HTMLInputElement]

tips:页面上不能出现相同id的元素。如果出现相同id的元素,我们通过id获取这个元素的时候,只能获取到第一个。

②获取页面的所有的元素

document.all; 这里返回的是一个数组

    var all = document.all;
l(all);

③获取指定类型的元素

documetn.xxxx

  • Document.anchors

  • Document.body

  • Document.forms

  • Document.images

  • Document.links

④几个常用的获取页面一组元素的API

document.getElementsByTagName(tagName) : 获取指定标签名的一组元素,返回一个对象数组。

Document.getElementsByClassName(): 获取一组有相同的class的元素。

document.querySelector(selector): 返回第一个符合选择器要求的dom元素,这里的selector就是CSS的选择器

document.querySelectorAll(selector): 获取所有的符合指定的选择器的元素的数组

案例:

    // 通过标签的名字获取一组元素
var divs = document.getElementsByTagName("div");
l(divs);
alert(divs);
for(var x = 0 ; x < divs.length;x ++){
l(divs[x]);
}

alert一个HTMLdom元素集合:

object HTMLCollection

控制台输出:

 HTMLCollection(2)[div,div]

这些集合可以按照数组的方式进行遍历。

其他的API的案例:

    // 通过类名获取
var es = document.getElementsByClassName("red");
l(es);

tips: 只要这个标签拥有这个类名即可,不在乎是否还有其他的类名。

通过CSS 选择器选择元素:

    // 通过类选择器获取一个元素(如果有多个,只获取第一个)
var es = document.querySelector("table .red");
l(es);
    // 通过类选择器获取一组元素
var es = document.querySelectorAll(".red,.blue");
l(es);

[2]使用DOM操作标签的属性

所谓操作标签的属性,就是给标签的属性赋值和获取标签的属性值。

比如之前用过的 xxxx.value

基本的语法:

var xxDom = getxxxx/queryxxxx
// 获取属性值
var attrValue = xxDom.属性名
// 设置属性值
xxDom.属性名 = attrValue

几乎所有的属性值都可以操作。

几个特殊的属性值:

readonly,disabled,checked,selected

这些属性在HTML标签中存在即生效。但是在JS中,只有设置为true才,false就是不生效。

案例1:获取和设置输入框的value属性

    <h2>获取和设置输入框的value属性</h2>
<input type="text" id="username">
<input type="button" value="哈哈" onclick="getUserName()">
<input type="text" id="result">
<script type="text/javascript">
function getUserName(){
var usernameDom = $("username");
var resultDom = $("result");
resultDom.value = usernameDom.value;
}
</script>

案例2:设置图片的src属性:

    <div>
<img style="border: 1px solid;" id="bigImg" src="images/img-1.jpg" alt="">
</div>
<div>
<ul>
<li style="display: inline-block;">
<img onmouseover="showImg('1')" src="images/img-1.jpg" width="30" border="1px solid;" alt="">
</li>
<li style="display: inline-block;">
<img onmouseover="showImg('2')" src="images/img-2.jpg" width="30" border="1px solid;" alt="">
</li>
<li style="display: inline-block;">
<img onmouseover="showImg('3')" src="images/img-3.jpg" width="30" border="1px solid;" alt="">
</li>
<li style="display: inline-block;">
<img onmouseover="showImg('4')" src="images/img-4.jpg" width="30" border="1px solid;" alt="">
</li>
<li style="display: inline-block;">
<img onmouseover="showImg('5')" src="images/img-5.jpg" width="30" border="1px solid;" alt="">
</li>
<li style="display: inline-block;">
<img onmouseover="showImg('6')" src="images/img-6.jpg" width="30" border="1px solid;" alt="">
</li>
</ul>
</div>
<script type="text/javascript">
function showImg(index){
// 获取大图片的DOM对象
var bigImg = $("bigImg")
// 修改图片的src属性
bigImg.src = "images/img-"+index+".jpg";
}
</script>

案例3:全选和全不选

    <div>
兴趣爱好:
<input name="enjoy" type="checkbox" value="1">LOL
<input name="enjoy" type="checkbox" value="2">KTV
<input name="enjoy" type="checkbox" value="3">捏脚
<input name="enjoy" type="checkbox" value="4">打麻将
<input name="enjoy" type="checkbox" value="5">学js
<input name="enjoy" type="checkbox" value="6">做作业
<input name="enjoy" type="checkbox" value="7">健身
</div>
<div>
<input type="button" value="全选" onclick="checkAll(true)">
<input type="button" value="全不选" onclick="checkAll(false)">
<input type="button" value="反选" onclick="resCheckAll()">
<input type="checkbox" onclick="checkInput()" id="ckAll"> 全选
</div>
<script type="text/javascript">
function checkAll(ck){
// 选择所有的复选框
var enjoys = document.querySelectorAll("[name='enjoy']");
for(var x = 0;x < enjoys.length;x ++){
if(enjoys[x].type=='checkbox'){
enjoys[x].checked = ck;
}
}
}
// 反选
function resCheckAll(){
// 选择所有的复选框
var enjoys = document.querySelectorAll("[name='enjoy']");
for(var x = 0;x < enjoys.length;x ++){
if(enjoys[x].type=='checkbox'){
enjoys[x].checked = !enjoys[x].checked;
}
}
}
function checkInput(){
// 获取当前的checkbox
var ckAll = $("ckAll");
// 选择所有的复选框
var enjoys = document.querySelectorAll("[name='enjoy']");
for(var x = 0;x < enjoys.length;x ++){
if(enjoys[x].type=='checkbox'){
enjoys[x].checked = ckAll.checked;
}
}
}
</script>

案例4:是否启用

    <input type="checkbox" onclick="enableBtn(this)"> 同意 xxxxxxxxxxx<br/>
<input type="button" id="btn" value="不可以使用" disabled>
<script>
function enableBtn(e){
var btn = $("btn");
if(e.checked){
btn.disabled = false;
btn.value = "可以点击的按钮";
}else{
btn.disabled = true;
btn.value = "不可以使用";
}
}
</script>

[3]使用DOM操作标签的样式

①直接修改标签的class

tips:class本身是标签的属性。我们修改标签的class其实就是通过属性操作修改class的值。

案例1:

        <style type="text/css">
.red{color:red;}
.bigFont{font-size: 36px;}
</style>
<p id="title" class="bigFont">《亏华宝殿》</p>
<p>
<input type="button" value="红" onclick="addRedClass()">
<input type="button" value="不红" onclick="removeRedClass()">
</p>
<script type="text/javascript">
function addRedClass(){
var titleDom = $("title")
// 操作元素的class属性,在JS中要使用className
titleDom.className=titleDom.className + " red";
}
function removeRedClass(){
var titleDom = $("title")
// 操作元素的class属性,在JS中要使用className
titleDom.className=titleDom.className.replace("red","");
}
</script>

tips:标签的class属性在js中是className。

案例2:

	<style type="text/css">
		.showImg{display: block;}
		.hidImg{display: none;}
	</style>
	<input type="button" value="显示" onclick="$('ykImg').className='showImg'">
	<input type="button" value="隐藏" onclick="$('ykImg').className='hidImg'">
	<input type="button" value="走你" onclick="$('ykImg').className=$('ykImg').className=='showImg'?'hidImg':'showImg'">
	<br/>
	<img src="images/img-2.jpg" id="ykImg">

②操作标签的样式属性

我们知道标签都有属性style。 我们可以通过style属性直接设置标签的样式。

这种样式,我们也称之为行样式。

<div style='boder:1px solid;'></div>

所以我们可以通过操作style属性的某些值来操作元素的样式。

获取样式属性的语法:

var value = xxxDom.style.xxxx

var color = divDom.style.backgroundColor;

设置样式属性的语法:

xxxDom.style.xxx = value;

divDom.style.borderColor = "#f0f0f0";

所有的样式都在 dom.style属性里面的。

在css中的样式属性名,如果中间是使用“-”连接的,则在JS中的属性名是:去掉“-”,让属性名符合js变量的驼峰命名规则即可。 比如 样式属性"background-color" --> backgroundColor

案例1:修改body的背景颜色

    <input type="button" value="红" onclick="document.body.style.backgroundColor='green'">
<input type="button" value="绿" onclick="document.body.style.backgroundColor='red'">
<input type="button" value="黄" onclick="document.body.style.backgroundColor='pink'">
<input type="button" value="粉" onclick="document.body.style.backgroundColor='yellow'">

案例2:折叠菜单

    <style>
li{
list-style: none;
}
</style>
<ul>
<li style="cursor: pointer;" onclick="showMenu('menu-user')">用户管理</li>
<li id="menu-user" style="display: none; margin-left: 15px; width: 120px;">
<div><a href="">添加用户</a></div>
<div><a href="">用户列表</a></div>
</li>
<li style="cursor: pointer;" onclick="showMenu('menu-pro')">产品管理</li>
<li id="menu-pro" style="display: none; margin-left: 15px; width: 120px;">
<div><a href="">添加产品</a></div>
<div><a href="">产品列表</a></div>
</li>
<li style="cursor: pointer;" onclick="showMenu('menu-order')">订单管理</li>
<li id="menu-order" style="display: none; margin-left: 15px; width: 120px;">
<div><a href="">添加订单</a></div>
<div><a href="">订单列表</a></div>
</li>
</ul>
<script type="text/javascript">
function showMenu(menuId){
var menu = $(menuId);
if(menu.style.display!='none'){
menu.style.display="none";
}else{
menu.style.display="block";
}
}
</script>

案例3:选项卡

        <style type="text/css">
.tab-li{
display: inline-block; border: 1px solid; border-radius: 5px 5px 0px 0px; cursor: pointer;
font-size: 16px;
}
.content{
width: 100%;
height: 275px;
border-top: 1px solid;
display: none;;
}
ul{
font-size: 0px;
}
</style>
<div style="width: 500px; height: 300px; border: 1px solid;">
<div>
<ul>
<li onclick="showTab('tab1',this)" style="" class="tab-li">选项卡1</li>
<li onclick="showTab('tab2',this)" class="tab-li">选项卡2</li>
<li onclick="showTab('tab3',this)" class="tab-li">选项卡3</li>
</ul>
</div>
<div>
<div class="content" style="display: block; " id="tab1">
第一个选项卡的内容
111111111111111111111
</div>
<div class="content" id="tab2" style="">
第一个选项卡的内容
22222222222222222222222
</div>
<div class="content" id="tab3" style="">
第一个选项卡的内容
33333333333333333333333
</div>
</div>
</div>
<script type="text/javascript">
function showTab(activeId,e){
// 显示对应的选项卡
// 1. 将所有的选项卡内容div隐藏
var contents = document.getElementsByClassName("content");
for(var x = 0;x < contents.length;x ++){
contents[x].style.display="none";
}
// 2. 将当前的选项卡内容显示出来
var currContent = $(activeId);
currContent.style.display="block";
// 让当前的标签处于选中状态
// 1. 去除所有的tab-li的背景颜色
var lis = document.getElementsByClassName("tab-li");
for(var j = 0;j < lis.length;j++){
lis[j].style.backgroundColor="#fff";
}
// 给当前的li添加背景颜色
e.style.backgroundColor='red';
}
</script>
    <div id="box" style="width: 255px; height: 255px;border:1px solid"
onmousemove="stMove(event)"
onmouseout="stOut()"
onmouseover="stOver()"></div>
<span id="result"></span>
<script type="text/javascript">
function stOver(){
$("box").style.backgroundColor = "#ccc";
}
function stOut(){
$("box").style.backgroundColor = "#fff";
}
function stMove(e){
$("result").innerText=e.x+":"+e.y
}
</script>

[4]使用DOM操作标签的内容和结构

①动态的创建一个HTML元素。

直接使用字符串拼接一段HTML,并且写入到文档中。

    <script type="text/javascript">
document.write("<h2>哈哈</h2>");
</script>

我们可以通过document提供的API创建一个DOM对象。

API:  createElement(tagName)

案例:

    <!-- 准备一个空的DIV  -->
<div id="box" style="height: 50px; border: 1px solid;"></div>
<script type="text/javascript">
// 动态创建一个h2 对象
var h2Dom = document.createElement("h2");
       // 设置样式
h2Dom.style.color="red"
// 给h2中添加文本
h2Dom.innerHTML="嘻嘻嘻";
// 将h2添加到box-div中
document.getElementById("box").append(h2Dom);
</script>

②操作HTML中标签的内容。

HTML标签中的内容,指的是非自闭合标签。

在HTML中的要给标签内部写任何内置,直接写。

在JS中的DOM对象与标签内容相关的属性有两个:

  • innerText : 标签内部的文本,不会解析HTML标签。

  • innerHTML: 标签内部的内容,会自动解析HTML标签。

通过innerText和innerHTML获取和设置标签内容:

    <div id="text-div">
<a href="www.7dian.com">起点</a>
</div>
<div id="html-div">
<a href="www.7dian.com">起点</a>
</div>
<input type="button" value="change text" onclick="changeText()">
<input type="button" value="change html" onclick="changeHtml()">
<script type="text/javascript">
function changeText(){
var divDom = document.getElementById("text-div");
// 从text-div取出内部的内容,输出到控制台。
var str = divDom.innerText;
console.log(str);
// 准备新的内容写入text-div
divDom.innerText = "<h2>戴着假发的程序员</h2>";
}
function changeHtml(){
var divDom = document.getElementById("html-div");
// 从html-div取出内部的内容,输出到控制台。
var str = divDom.innerHTML;
console.log(str);
// 准备新的内容写入html-div
divDom.innerHTML = "<h2>戴着假发的程序员</h2>";
}
</script>

我们填入的内容是: <h2>戴着假发的程序员</h2> 浏览器将标签按照文本输出了。

控制台输出的内容:本身DIV中的内容:<a href="www.7dian.com">起点</a> 控制台只是输出了文本 -- 起点,没有标签

说明: 使用innnerText获取的内容会忽略内容中的HTML标签。 使用innnerText去设置内容的时候,也会忽略标签的作用,将标签按照文本的方式输出。

第二个按钮的效果:

戴着假发的程序员   <href="www.7dian.com">起点</a>

使用innerHTML设置内容,内容HTML标签会被解析运行。 使用innerHTML获取内容,不会忽略HTML标签。

③元素的添加和移除。

我们获得了某个DOM节点,假设这个DOM节点是空的,我们通过innerHTML就可以增加一个元素了,但是这个DOM节点已经存在元素了,不能这样操作会产生覆盖!

insert

要包含的节点.insertBefore(newNode,targetNode)

案例:

<p id="js">JavaScript</p>

<div id="list">

<p id="se">JavaSE</p>

<p id="ee">JavaEE</p>

</div>

<script>

var ee = document.getElementById('ee');

var js = document.getElementById('js');

var list = document.getElementById('list');

list.insertBefore(js,ee);

</script>

添加元素

API-1: Element.append()

Element.append 方法在 Element的最后一个子节点之后插入一组 Node 对象或 DOMString 对象。 被插入的 DOMString 对象等价为 Text 节点。

Element表示任何可以添加子元素的元素。其中Node表示所有的DOM对象。 DOMString就是一个字符串。

看一个案例理解一下:

案例1:创建新的dom对象,加入元素

        <ul id="msgs">            
</ul>
<input type="text" id="msg">
<input onclick="addMsg()" type="button" value="add">
<script type="text/javascript">
function addMsg(){
// 获取文本框对象
var textDom = document.getElementById("msg");
var value = textDom.value;
// 动态的创建一个li dom对象
var liDom = document.createElement("li");
// 在liDom中添加对应的文本
liDom.append(value);// DOMString -> String
// 将liDom加入ul
document.getElementById("msgs").append(liDom);// node
}
</script>

案例2:获取页面的dom对象,加入元素

    <input type="text" id="username" placeholder="请输入用户名">
<input type="button" onclick="gotoDiv()" value="走你">
<div style="border : 1px solid; height: 200px;" id="result">
</div>
<script type="text/javascript">
function gotoDiv(){
var resultDom = document.getElementById("result");
var usernameDom = document.getElementById("username");
// 将usernameDom加入到resultDom
resultDom.append(usernameDom);
}
</script>

Node.appendChild

**Node.appendChild()** 方法将一个节点附加到指定父节点的子节点列表的末尾处。如果将被插入的节点已经存在于当前文档的文档树中,那么 appendChild() 只会将它从原先的位置移动到新的位置(不需要事先移除要移动的节点)。

这意味着,一个节点不可能同时出现在文档的不同位置。所以,如果某个节点已经拥有父节点,在被传递给此方法后,它首先会被移除,再被插入到新的位置。若要保留已在文档中的节点,可以先使用

其实这个方法和append差不多,接收的参数肯定是Node。就是DOM对象。

看案例:

    <ul id="msgs">      
</ul>
<input type="text" id="msg">
<input onclick="addMsg()" type="button" value="add">
<script type="text/javascript">
function addMsg(){
// 获取文本框对象
var textDom = document.getElementById("msg");
var value = textDom.value;
// 动态的创建一个li dom对象
var liDom = document.createElement("li");
// 在liDom中添加对应的文本 这里不能使用appendChild
liDom.append(value);// DOMString -> String
// 将liDom加入ul   这里可以使用appendChild
document.getElementById("msgs").appendChild(liDom);// node
}
</script>

tips:appendChild不接受字符串。

删除元素

Element.remove()

**Element.remove()** 方法,把对象从它所属的 DOM 树中删除。

案例:

    <ul id="names"></ul>
<script type="text/javascript">
var ulDom = document.getElementById("names");
for(var x = 0;x < 10;x ++){
var liDom = document.createElement("li");
liDom.append("鸣人:"+x);
ulDom.append(liDom);
}
</script>
<input type="button" value="删除" onclick="removeMingren()">
<script type="text/javascript">
function removeMingren(){
// 先问,要删除索引为多的
var index = window.prompt('请输入索引','0');
// index就是输入的索引值
if(index){ //如果选择了取消,index就是undefined
// 获取所有的liDOM对象数组
var lis = document.getElementsByTagName("li");
// 遍历数组
for(var x = 0;x < lis.length;x ++){
// 找到要删除的元素的索引
if(index == x){
//删除当前的元素
lis[x].remove();
break;
}
}
}
}
</script>

Node.removeChild  先获取父节点,再通过父节点删除自己

Node.removeChild() 方法从DOM中删除一个子节点。返回删除的节点。

父节点.removeChild(子节点)

看案例:

    <div id="div1">
<input type="text" id="msg">
</div>
<div id="div2">

</div>
<input type="button" value="走你" onclick="zouni()">
<script type="text/javascript">
function zouni(){
// 将div1中的input移动到div2中。
// 获取DOM
var div1Dom = document.getElementById('div1');
var div2Dom = document.getElementById('div2');
var msgDom = document.getElementById('msg');
// div2Dom.append(msgDom);
// input从第一个div中删除
var dom = div1Dom.removeChild(msgDom);
div2Dom.append(dom);
}
</script>
//删除是一个动态的过程
father.removeChild(father.childen[0]);
father.removeChild(father.childen[1]);
father.removeChild(father.childen[2]);
注意:删除多个节点的时候,children 是在时刻变化的,删除节点的时候要注意!!

克隆元素

Node.cloneNode

Node.cloneNode() 方法返回调用该方法的节点的一个副本.

看案例:

    <div id="div1">
<input type="text" id="msg">
</div>
<div id="div2">

</div>
<input type="button" value="走你" onclick="zouni()">
<script type="text/javascript">
function zouni(){
// 将div1中的input移动到div2中。
// 获取DOM
var div2Dom = document.getElementById('div2');
var msgDom = document.getElementById('msg');
// 克隆msgDom
var newDom = msgDom.cloneNode();
// 将克隆出来的DOM对象加入div2
div2Dom.append(newDom);
}
</script>

综合案例1:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<ul id="names"></ul>
<script type="text/javascript">
var ulDom = document.getElementById("names");
for(var x = 0;x < 10;x ++){
var liDom = document.createElement("li");
liDom.append("鸣人:"+x);
ulDom.append(liDom);
}
</script>
<input type="button" value="删除" onclick="removeMingren()">
<script type="text/javascript">
function removeMingren(){
// 先问,要删除索引为多的
var index = window.prompt('请输入索引','0');
// index就是输入的索引值
if(index){ //如果选择了取消,index就是undefined
// 获取所有的liDOM对象数组
var lis = document.getElementsByTagName("li");
// 遍历数组
for(var x = 0;x < lis.length;x ++){
// 找到要删除的元素的索引
if(index == x){
//删除当前的元素
lis[x].remove();
break;
}
}
}
}
</script>
</body>
</html>

根据文档结构筛选DOM对象

几个关键词:

  • DOM对象 文档对象。页面元素对应的对象。

  • Element (元素) 就是我们常说的DOM对象。 Element不包含空文档节点的。

  • Node (节点) Node的范围是大于Element。 Node包含了空文档节点。

其中所有<xxx></xxx>的都是Element,也是Node。 但是代码的空格部分,不是Element,是TextNode。

几个API

  • Node.childNodes

Node.childNodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合(live collection)。

案例:

<h2>Node.childNodes</h2>
<div id="box">
   <span>123</span>
   <a href="">百度</a>
   <ul>
       <li>1</li>
       <li>2</li>
   </ul>
</div>
<script>
   // 获取box
   var boxDom = document.getElementById("box");
   // 获取boxDom下的所有的子元素节点 这里的节点包含的空文本节点
   var nodes = boxDom.childNodes;
   // 我们可以将nodes当作数组来处理。
   console.log(nodes);
</script>
  • Element.children

Element.children 是一个只读属性,返回 一个Node的子elements ,是一个动态更新的 HTMLCollection。

和Node.childNodes的区别就是不包含空的文本节点。

案例:

<script>
   // 获取box
   var boxDom = document.getElementById("box");
   // 获取boxDom下的所有的子元素节点 这里的节点不包含的空文本节点
   var nodes = boxDom.children;
   // 我们可以将nodes当作数组来处理。
   console.log(nodes);
</script>
  • Node.firstChild

  • Node.lastChild

  • Element.firstElementChild

  • Element.lastElementChild

  • Node.parentNode 获取父节点

  • Node.parentElement 获取父元素

案例:

<h2>
  - Node.parentNode 获取父节点
- Node.parentElement 获取父元素
</h2>
<div>
   <ul>
       <li>卡卡西 <input type="button" value="删" onclick="removeLi(this)"></li>
       <li>卡卡东 <input type="button" value="删" onclick="removeLi(this)"></li>
       <li>卡卡南 <input type="button" value="删" onclick="removeLi(this)"></li>
       <li>卡卡北 <input type="button" value="删" onclick="removeLi(this)"></li>
       <li>卡卡中 <input type="button" value="删" onclick="removeLi(this)"></li>
   </ul>
</div>
<script>

   function removeLi(ele){
       // 这里的ele表示当前元素 这里的当前元素是input
       // 获取父元素
       var liDom = ele.parentElement;
       // 删除
       liDom.remove();
  }
</script>
 

选择兄弟节点:

  • Node.nextSibling

Node.nextSibling 是一个只读属性,返回其父节点的 childNodes 列表中紧跟在其后面的节点,如果指定的节点为最后一个节点,则返回 null。

  • Node.previousSibling

返回当前节点的前一个兄弟节点,没有则返回null.

  • nextElementSibling

nextElementSibling 返回当前元素在其父元素的子元素节点中的后一个元素节点,如果该元素已经是最后一个元素节点,则返回null,该属性是只读的.

  • previousElementSibling

previousElementSibling 返回当前元素在其父元素的子元素节点中的前一个元素节点,如果该元素已经是第一个元素节点,则返回null,该属性是只读的.

案例:

<h2>兄弟节点的筛选</h2>
<div>
   <span>第一个元素</span>
   <input type="button" value="click me" onclick="stClick(this)">
   <a href="www.7dianit.com">起点编程</a>
</div>
<script>
   function stClick(ele){
       console.log("下一个节点:"+ele.nextSibling);
       console.log("下一个元素:"+ele.nextElementSibling);
       console.log("上一个节点:"+ele.previousSibling);
       console.log("上一个元素:"+ele.previousElementSibling);
  }
</script>

[5]使用DOM操作标签的事件

了解的事件

  • onclick 单击事件

  • onchange 修改事件

  • ondbclick 双击事件

  • onfocus 获得焦点的事件

  • onblur 失去焦点的事件

表单元素的事件案例:

<input id="username" type="text" value="请输入用户名"
onblur="stBlur()"
onfocus="stFocus()">
<script>
function stFocus(){
$("username").value="";
}
function stBlur(){
$("username").value="请输入用户名";
}
</script>

  • onmouseover 鼠标悬浮事件

  • onmouseout 鼠标离开的事件

  • onmousemove 鼠标移动事件

  • onmouseleave 鼠标离开事件

  • onmouseenter 鼠标进入事件

  • onmousedown 鼠标按下事件

  • onmouseup 鼠标松开事件

鼠标事件案例:

<div id="box" style="width: 255px; height: 255px;border:1px solid"
onmousemove="stMove(event)"
onmouseout="stOut()"
onmouseover="stOver()"></div>
<span id="result"></span>
<script type="text/javascript">
function stOver(){
$("box").style.backgroundColor = "#ccc";
}
function stOut(){
$("box").style.backgroundColor = "#fff";
}
function stMove(e){
$("result").innerText=e.x+":"+e.y
}
</script>

  • onkeydown 键盘按下的事件

  • onkeyup 键盘松开事件

  • onkeypress 按键事件

键盘事件案例:

<body onkeydown="stKeydown(event)">
<div style="width: 200px; height: 200px; border: 1px solid;" id="panel" >
</div>
<script>
function stKeydown(e){
console.log(e);
$("panel").innerHTML="按下了"+e.code+"键:"+e.key;
}
</script>
</body>

不熟悉的事件:

  • onload 加载事件

  • onscroll 滚动事件

  • onsubmit 表单提交事件

  • oncontextmenu 右键菜单事件

  • onselect 被选择的时候

几乎所有的事件都可以传递参数:

event表示事件源。 如果是鼠标事件可以获取鼠标的属性。 如果是键盘事件,我们可以通过event获取按键的key和code。

onload事件

常见的就是给body添加load事件。

看问题:

<script>
function doLoad(){
  var btn = document.getElementById("btn");
  console.log(btn); // null
}
</script>
<body onload="doLoad()">
  <!--等body全部加载完成之后,再执行doLoad(),而且是自动执行-->
  
<input type="button" value="click me" id="btn">
<script>
  console.log(1231213);
</script>
</body>

有时我们希望有些程序页面加载之后自动执行。这些程序不是写在函数中的。但是如果这些程序中有获取页面元素的部分,一定要将这些程序写在HTML代码的最后面。

如果希望在页面加载完成之后再执行这些程序,可以使用body的onload事件。

但是其实常见的实际应用都是选择将要自动执行的程序放在HTML文档最后面。

问题:onload意思是等页面完全加载完成再执行。 如果我们自己将程序写在HTML最后,页面结构完成之后,程序就可以执行。

onscroll事件

滚动条滚动的时候触发这个事件。

    <h2>滚动事件</h2>
    <div onscroll="doScroll(this)" style="overflow:auto; width: 300px; height: 100px; border: 1px solid;">
        <div style="width: 600px; height: 50px; "></div>
    </div>
    <script>
        function doScroll(ele){
            console.log(ele.scrollLeft);
        }
    </script>

oncontextmenu 右键菜单事件

    <div oncontextmenu="alert(1)" style="width: 200px; height: 200px; border: 1px solid;"> </div>

onselect 被选择的时候

只有在文本框和文本域内选择文本才会触发select事件.

    <div>
        <input type="text" onselect="alert(1)">
    </div>

onsubmit 表单的提交事件

这个事件是form标签的事件。

表单的主要作用是收集数据,最终会将数据提交到表单的action指定的位置。

提交表单需要使用 submit按钮或者image按钮。

看案例:

    <!-- 目前没有处理登陆的业务,这里就是模拟 -->
    <form action="doLogin.html" >
        <p><input type="text" name="username" placeholder="请输入用户名"></p>
        <p><input type="text" name="userpass" placeholder="请输入密码"></p>
        <p>用户类型:<select name="usertype" id="">
            <option value="1">管理员</option>
            <option value="2">操作员</option>
            <option value="3">普通用户</option>
        </select></p>
        <p>
            登陆类型:
            <input type="radio" value="1" name="logintype">基础登陆
            <input type="radio" value="2" name="logintype">高级登陆
        </p>
        <p>
            <input type="submit" value="登陆">
        </p>
    </form>

输入内容,点击提交:

我们会发现,当点击登陆按钮(submit)的时候,会将表单中的内容阻止成: name=value&name=value...

使用“?”连接在表单的action指向的url: doLogin?username=admin&userpass=123456。。。

表单中的所有的input,select, textarea都是表单域。

所有的表单域都应该有name属性。name属性是可以相同的。

当我们提交表单的时候,浏览器会自动将表单域的内容按照 name=value&name=value的方式使用“?”连接在提交的url(form标签的action中指定的)后面.

onsubmit是表单提交的事件,当onsubmit返回false的时候,这个表单无法提交。只有当onsubmit不return false的时候,表单才能提交。

我们往往在onsubmit中对表单的数据进行校验:

案例:

    <script>
        function checkForm(){
            var username = document.querySelector("[name='username']").value;
            if(username==''){
                alert("用户名不能为空");
                return false;
            }
            var userpass = document.querySelector("[name='userpass']").value;
            if(userpass==''){
                alert("密码不能为空");
                return false;
            }
            return true;
        }
    </script>
    <!-- 目前没有处理登陆的业务,这里就是模拟 -->
    <form onsubmit="return checkForm()" action="doLogin.html">
        <p><input type="text" name="username" placeholder="请输入用户名"></p>
        <p><input type="text" name="userpass" placeholder="请输入密码"></p>
        <p>用户类型:<select name="usertype" id="">
            <option value="1">管理员</option>
            <option value="2">操作员</option>
            <option value="3">普通用户</option>
        </select></p>
        <p>
            登陆类型:
            <input type="radio" value="1" name="logintype">基础登陆
            <input type="radio" value="2" name="logintype">高级登陆
        </p>
        <p>
            <input type="submit" value="登陆">
        </p>
    </form>
特别注意: onsubmit 绑定一个提交检测的函数,将这个结果返回给表单,使用submit 接收  onsubmit="return checkForm()"
//追加: MD5加密算法:可以解决在输入密码登录提交表单后,在抓包的时候是密码是以明文显示
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>

<span>密码</span><input type="password" id="input-password">

<input type="hidden" id="md5-password" name="password">//可以解决密码框密码加密之后一长串的字符出现

//验证用pwd 给浏览器抓包用md5pwd md5pw加了name="password"属性 没有name属性无法提交

var pwd = document.getElementById("input-password");

var md5pwd = document.getElementById("md5-password");

md5pwd.value = md5(pwd.value);

通过JS给元素绑定和解绑事件

看问题:

    <input type="text" id="name" placeholder="请输入一个名字">
    <input type="button" value="添加" onclick="addName()">
    <ul id="names"></ul>
    <script>
        function addName(){
            var textDom = document.getElementById("name");
            var ulDom = document.getElementById("names");
            // 取出输入的name
            var name = textDom.value;
            if(name == ''){
                return;
            }
            // 创建一个li
            var liDom = document.createElement("li");
            liDom.append(name);
            // 准备一个删除按钮
            var btnDom = document.createElement("input");
            btnDom.type = "button";
            btnDom.value = "删除";
            // 给按钮事件
            // btnDom.onclick="remLi(this)" 这是文本属性的绑定方式。
            // 事件需要的就是一个函数,直接赋值一个函数即可
            btnDom.onclick = function(){
                // 这里的this表示触发这个事件的元素本身。
                this.parentElement.remove();
            }
            liDom.append(btnDom);
            ulDom.append(liDom);
        }
        function remLi(ele){
            ele.parentElement.remove();
        }
    </script>

动态给元素绑定事件方式1:

// 获取dom对象
var xxxDom = ......
// 绑定事件  第一种方式
xxxDom.onxxxxx = function(){
    // 事件的执行代码   这里的this就表示当前触发这个事件的元素本身
}
// 绑定事件  第二种方式 
// 定义一个函数
function fn(){// 事件的执行代码   这里的this就表示当前触发这个事件的元素本身}
// 给元素绑定事件
xxxDom.onxxxx = fn;  // 千万不要有()

案例1: 常见的超链接编写方式

    <!-- href="javascript:void(0)" 阻止这个超链接的连接效果 -->
    <a href="javascript:void(0)" id="stLink">show msg</a>
    <script>
        var linkDom = document.getElementById("stLink");
        // 动态的给超链接绑定一个事件
        linkDom.onclick=function(){
            // 可以使用js完成一个连接   很多时候这里往往是一个内部的地址。
            // location.href="manager/user/adduser/1"
            location.href = "http://www.baidu.com";
        }
    </script>

案例2:拖拽

    <div id="win" style="width: 200px; height: 200px; ">
    </div>
    <script>
        var win = document.getElementById("win");
        
        // 绑定事件鼠进入的事件
        win.onmouseenter = function(){
            // 调整样式
            win.style.position = "absolute";
            win.style.left="0px";
            win.style.top="0px";
        }
        // 鼠标按下的事件
        win.onmousedown=function(event){
            // 记录鼠标当前的位置
            var mx = event.x;
            var my = event.y;
            // 绑定鼠标移动事件
            win.onmousemove=function(ent){
                // 获取此时鼠标的位置
                var nx = ent.x;
                var ny = ent.y;
                // 移动当前元素
                var left = parseInt(win.style.left);
                var top = parseInt(win.style.top);
                win.style.left = (left + (nx - mx)) + "px";
                win.style.top = (top + (ny - my)) + "px";
                // 覆盖之前定义的鼠标的位置
                mx = nx;
                my = ny;
            }
        }
    </script>

解绑元素的事件方式1:

语法:

// 解绑事件,就是将事件置空
xxxDom.onxxx = null;

案例:

    <div id="div" style="border: 1px solid; height: 200px; width: 200px;"></div>
    <input type="button" value="绑定事件" onclick="bindMouseEventOnDiv()">
    <input type="button" value="解绑事件" onclick="unbindMouseEventOnDiv()">
    <script>
        function bindMouseEventOnDiv(){
            // 获取dom元素
            var divDom = document.getElementById("div");
            // 绑定鼠标移动事件
            divDom.onmousemove=function(event){
                this.innerHTML = event.x+":"+event.y;
            }
        }
        function unbindMouseEventOnDiv(){
            // 获取dom元素
            var divDom = document.getElementById("div");
            // 解绑事件
            divDom.onmousemove = null;
        }
    </script>

第二种方式给元素绑定和解绑事件

绑定事件:

xxxDom.addEventListener(type,fn)

type: 事件类型, 去掉on的事件类型。比如要绑定 onclilck -> click

fn: 事件的处理函数。

解绑事件:

xxxDom.removeEventListener(type,fn-name)

type:还是类型

fn-name: 表示要移除的函数的名字。

tips: 同一种类型的事件,可以绑定多个函数。所以再解绑的时候,就需要指定要解绑的函数的名字。

案例:

    <div id="div" style="border: 1px solid; height: 200px; width: 200px;"></div>
    <input type="button" value="绑定事件" onclick="bindMouseEventOnDiv()">
    <input type="button" value="解绑事件" onclick="unbindMouseEventOnDiv()">
    <script>
        function bindMouseEventOnDiv(){
            // 获取dom元素
            var divDom = document.getElementById("div");
            // 绑定鼠标移动事件
            divDom.addEventListener("mousemove",showMouseLocation);
            // 再绑定一个事件,还是mousemove
            divDom.addEventListener("mousemove",changeBackgroundColor);
        }

        function unbindMouseEventOnDiv(){
            // 获取dom元素
            var divDom = document.getElementById("div");
            // 解绑事件
            divDom.removeEventListener("mousemove",showMouseLocation)
        }

        // 准备几个事件
        // 显示鼠标的位置
        function showMouseLocation(event){
            // 获取dom元素
            var divDom = document.getElementById("div");
            // 显示鼠标的位置
            divDom.innerHTML = event.x+":"+event.y;
        }

        // 鼠标按下的时候,修改div的背景颜色
        function changeBackgroundColor(event){
            // 获取dom元素
            var divDom = document.getElementById("div");
            divDom.style.backgroundColor="rgb(255,"+event.x+","+event.y+")";
        }
    </script>

事件冒泡

HTML文档本身就是"一棵树";

默认情况下一个元素的事件被触发之后,会自动传播到父节点。

看案例:

    <div id="div1" style="width: 500px; height: 500px; ">
        <div id="div2" style="width: 300px; height: 300px; margin: 100px 100px; ">
            <div id="div3" style=" width: 100px; height: 100px; margin: 100px 100px; "></div>
        </div>
    </div>
    <script>
        window.onload=function(){
            // 这里代码默认会在页面加载完成之后自动执行
            document.getElementById("div1").onclick=function(){
                console.log("div1");
            }
            // document.getElementById("div2").onclick=function(){
            //     console.log("div2");
            // }
            document.getElementById("div3").onclick=function(){
                console.log("div3");
            }
        }
    </script>

阻止事件冒泡

  • event.stopPropagation

阻止捕获和冒泡阶段中当前事件的进一步传播。

但是,它不能防止任何默认行为的发生; 例如,对链接的点击仍会被处理。

    <div id="div1" style="width: 500px; height: 500px; ">
        <div id="div2" style="width: 300px; height: 300px; margin: 100px 100px; ">
            <div id="div3" style=" width: 100px; height: 100px; margin: 100px 100px; "></div>
        </div>
    </div>
    <script>
        window.onload=function(){
            // 这里代码默认会在页面加载完成之后自动执行
            document.getElementById("div1").onclick=function(event){
                console.log("div1");
            }
            document.getElementById("div2").onclick=function(event){
                console.log("div2");
            }
            document.getElementById("div3").onclick=function(event){
                console.log("div3");
                // 阻止事件传播
                event.stopPropagation();
            }
        }
    </script>
补充:

DOM对象的类型是Element。

一个dom对象就对应一个HTML元素。HTML元素有属性。几乎每一个属性都在DOM对象上有对应的。一些特殊的:class对应className。

HTML元素没有innerTHML和innerText属性,但是dom对象有。

HTML标签有的属性是没有的,但是我们可以写比如:

<div id="div" name="kakaxi"></div>

但是这个td对应的DOM对象是没有这个属性的。

    <script>
       console.log(document.getElementById("div").name);// undefined
   </script>

但是DOM对象本身就是js对象。JS对象的属性是可以随意扩展的。

比如:

       // 自定义的对象
       var p = {};
       // 设置属性
       p.name="卡卡西";
       console.log(p.name);// 卡卡西
       // 获取一个DOM对象
       var div = document.getElementById("div");
       // 通过JS设置一个属性(这个属性HTML标签是没有的)
       div.sellPoint="DIV很强大";
       console.log(div.sellPoint); // 可以获取到这个属性
  • 当我们写HTML的时候,如果强行的给某个标签写了一个本来没有的属性,这个属性在标签层面就是存在的。通过JS获取这个标签的DOM对象之后,无法获取这个属性。因为DOM和标签没有这个属性的映射。

  • 同样的道理,在DOM对象上设置一个不存在的属性,也无法映射到HTML标签。

但是有时,我们就是希望DOM和HTML标签之间可以映射HTML本身没有规定的属性。

JS提供了专门的API操作属性:

  • Element.getAttribute(attrName) 获取指定名称的属性值

  • Element.setAttribute(attrName,attrValue) 设置指定的属性

  • Element.getAttributeNames() 获取这个元素的所有的属性的名字

案例:

    <div id="div" name="kakaxi"></div>
   <script>
       console.log(document.getElementById("div").name);
       // 自定义的对象
       var p = {};
       // 设置属性
       p.name="卡卡西";
       console.log(p.name);// 卡卡西
       // 获取一个DOM对象
       var div = document.getElementById("div");
       // 通过JS设置一个属性(这个属性HTML标签是没有的)
       div.sellPoint="DIV很强大";
       console.log(div.sellPoint); // 可以获取到这个属性
       console.log(document.getElementById("div").sellPoint);
   </script>
   <p id="p" name="一句诗" age="500">离离原上草</p>
   <script>
       var pdom = document.getElementById("p");
       // 获取所有的属性名字
       var names = pdom.getAttributeNames();
       for(var x = 0;x < names.length;x ++){
           console.log(names[x]);
      }
       // 获取属性值
       console.log(pdom.getAttribute("name"));
       console.log(pdom.getAttribute("age"));
       // 设置一个属性
       pdom.setAttribute("class","abc");
       pdom.setAttribute("tel","13813813838");
   </script>
father.removeChild(father.childen[0]);