文章目录
宿主对象(DOM)
DOM,全称Document Object Model文档对象模型
JS中通过DOM对HTML文档进行操作,理解DOM就可以随意操作WEB页面
文档:表示整个的HTML网页文档
对象:表示将网页中的每一个部分都准换为了一个对象
模型:使用模型来表示对象之间的关系,这样方便我们获取对象
DOM对象属性
innerHTML // 节点的文本值
parentNode // 节点的父节点
childNodes // 节点的子节点
attributes // 节点的属性节点
nodeValue //规定节点的值 元素节点的它是undefined或者 null 文本节点的它是文本本身 属性节点的它是属性值
<a id="i1" href="http://www.baidu.com">hello</a>
var x = document.getElementById('i1')
console.log(x.nodeValue) // null
console.log(x.firstChild.nodeValue) // hello
value : 属性可设置或返回选项的值。
节点
-
Node,是构成我们网页的最基本的组成部分,网页中的每一个部分都可以成为是一个节点
-
常用节点分类
-
文档节点:整个html文档 nodeName(#document)
-
元素节点:HTML文档中的HTML标签 nodeName(标签名)
-
属性节点:元素的属性 nodeName(属性名)
-
文本节点:HTML标签中的文本内容 nodeName(#text)
-
<a id='demo' href="#">hello</a> // 元素节点 ---属性节点----属性节点--文本节点---
-
事件
- 事件就是文档或浏览器窗口中发生的一些特定的交互瞬间
- js与html之间的交互是通过事件实现的
事件句柄:能够使 HTML 事件触发浏览器中的行为,比如当用户点击某个 HTML 元素时启动一段 JavaScript。下面是一个属性列表,可将之插入 HTML 标签以定义事件的行为。
在事件对应的属性中设置一些js代码,这样当事件被触发时,这些代码将会被执行
<button id="btn" onclic="alert('hello')">click</button> // 结构和行为耦合,不放便维护,不推荐
<button id="btn" onclic="alert('hello')">click</button>
<script>
// 获取按钮
var btn = document.getElementById("btn");
// 绑定一个单击事件
// 单击响应函数,当事件被触发的时候执行
btn.onclick = function(){
alert('hi');
}
</script>
事件对象
- 当事件向应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数
- 在事件对象中封装了当前事前的一切信息,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。事件通常与函数结合使用,函数不会在事件发生前被执行!
// onmousemove 该事件将会在鼠标在元素中移动触发
<div id="area"></div>
var area = document.getElementById('area');
area.onmousemove = function(event){ // 形参包含浏览器封装的信息
var x = event.clientX; // 获取鼠标指针的水平坐标
var y = event.clientY; // 获取鼠标指针的垂直坐标
}
//在IE8中,响应函数被触发时,浏览器不会传递事件对象
// 在IE8及以下的浏览器中,是将事件对象作为window对象的属性进行保存的
var x = window.event.clientX;
// 兼容性的做法
event = event || window.event; // 或是找true 第一个是true就返回第一个,不是则返回第二个
// 拖动div标签
<div id="i1"></div>
<style>
width:200px;
height:200px;
background-color:red;
position:absoulte; // 绝对定位,必须要设置
</style>
<script>
var div = document.getElementById("i1");
document.onmousemove = function(e){ // 这样在网页上可以随意移动
var x = e.pageX;
var y = e.pageY; // 鼠标相对于页面的位置 event.clientY:获取的是可见窗口 IE8不支持
//设置div的偏移量
div.style.left = x + "px";
div.style.top = y + "px";
}
</script>
// 火狐等浏览器人会滚动条是HTML的
var s = document.body.scroTop || document.documentElement.scrollTop; // 兼容
// 目的是为了获取坐标,而解决div拖动在当前窗口的兼容性问题
</style>
<script>
var s = document.body.scroTop || document.documentElement.scrollTop;
var div = document.getElementById("i1");
document.onmousemove = function(e){ // 这样在网页上可以随意移动
var x = e.clientX;
var y = e.clientX; // 鼠标相对于页面的位置 event.clientY:获取的是可见窗口 IE8不支持
//设置div的偏移量
div.style.left = x + "px";
div.style.top = y + s + "px";
}
</script>
事件的冒泡
-
冒泡指的是相同事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发 (onclick)
-
在开发中大部分都是有用的,如果不希望发生冒泡,可以取消冒泡
-
<script> var div = document.getElementById("i1"); document.onmousemove = function(e){ alert = e || window.e; alert('取消冒泡'); e.cancelBubble = true; } </script>
事件的委派
-
将事情统一绑定给元素共同的祖先元素,这样后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件
-
利用了冒泡,通过委派可以减少事件绑定的次数
-
<button id="btn">添加链接</button> <ul id='i1'> <li><a href="#" class="link">1</a></li> <li><a href="#" class="link">1</a></li> <li><a href="#" class="link">1</a></li> </ul> <script> var ul = document.getElementById("i1"); var btn = document.getElementById("btn"); btn.onclick = function(){ var li = document.createElement("li"); li.innerHTML = "<a href='#' class="link">hello</a>" ul.appendChild(li); } ul.onclick = function(e){ // 如果触发的对象事我们期望的元素则执行,否则不执行 event = event || window.wvwnt; // target 表示触发事件的对象 if(e.target.className == "link"){ alert('hi'); } } </script>
事件的绑定
-
使用对象.事件 = 函数 的形式绑定相应函数,不能绑定多个,后面的将会把前面的覆盖掉
-
addEventListener() IE8 和一下不支持
- 1.事件的字符串,不要on
- 2.回调函数,当事件触发时该函数会被调用
- 3.是否在捕获阶段触发事件,一般都取false
-
btn.addEventListener("click",function(){},false) ;
-
attachEvent() IE8
-
1.事件的字符串,要on
-
2.回调函数,当事件触发时该函数会被调用
-
执行顺序是由后到前去执行
-
btn.attachEvent("onclick",function(){}) ;
-
-
定义一个函数,用于指定元素绑定响应函数
-
参数:
- obj 要绑定的对象
- eventStr 事件的字符串(不要on)
- 回调函数
-
function bind(obj,eventStr,callback){ // 大部分浏览器兼容 if(obj.addEventListener){ btn.addEventListener(eventStr,callback,false) ; }else{ // this是谁由调用方式决定 btn.attachEvent("on"+eventStr,function(){ callback.call(obj); }) ; } }
事件传播
- 微软认为事件由内到外执行,事件冒泡
- 网景公司认为事件应该是由外向内传播,事件的捕获行为
- W3C:综合了两个公司方案,将事件分为三个阶段
- 1.捕获阶段
- 在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
- 2.目标阶段
- 事件到达目标元素,捕获结束开始在目标元素上触发事件
- 冒泡阶段
- 事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件
- 如果希望从捕获阶段就可以执行,可以将addEventListener() 第三个参数改为true
- 一般不会这样使用
- 1.捕获阶段
浏览器加载顺序是从上到下执行
-
如果将script标签写到页面上面,在代码执行时,页面还没有加载
-
如果放在代码的上面,应该给window绑定一个onload事件,这样就可以正常执行了
-
window.onload = function(){ // 获取按钮 var btn = document.getElementById("btn"); // 绑定一个单击事件 // 单击响应函数,当事件被触发的时候执行 btn.onclick = function(){ alert('hi'); }
拖拽事件
拖拽流程
- 1.当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
- 2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove
- 3.当鼠标松开时,被拖拽元素固定在当前的位置 onmouseup
<div class="demo"></div>
<script>
window.onload = function(){
var demo = document.getElementById("demo")
demo.onmousedown = function(){
// 为documnet绑定移动事件
document.onmousemove = function(e){
e = e || window.e;
var left = e.clientX;
var top = e.clientY;
demo.style.left = left + "px";
demo.style.top = top +"px"
}
// 为document绑定一个鼠标松开的事件
document.onmouseup =function(){
document.onmousemove = null; // 取消移动事件
document.onmouseup = null; // 取消鼠标松开这个事件
}
}
}
</script>
// 鼠标位置与拖拽元素不一致的问题解决
<script>
window.onload = function(){
var demo = document.getElementById("demo")
demo.onmousedown = function(e){
// 为documnet绑定移动事件
e = e || window.e;
var c1 = e.clinetX - demo.offsetLeft;
var c2 = e.clientY - demo.offsetTop;
document.onmousemove = function(e){
e = e || window.e;
var left = e.clientX - c1;
var top = e.clientY - c2;
demo.style.left = left + "px";
demo.style.top = top +"px"
}
// 为document绑定一个鼠标松开的事件
document.onmouseup =function(){
document.onmousemove = null; // 取消移动事件
document.onmouseup = null; // 取消鼠标松开这个事件
}
// 当我们拖拽一个网页内的内容时,浏览器会默认去搜索
// 可以直接同过return false来取消默认行为
// 但是对IE8不行
return false;
}
}
</script>
// demo.setCapture(); 绑定这个事件后,所有鼠标按下的时间都会被这个元素捕获
// chrome调用会报错
demo.onmousedown = function(e){
// 会产生恶性循环,一直进行捕获,所以要销毁这个事情
if(demo.setCapture){
demo.setCapture(); // 设置demo捕获所有鼠标按下的事件
} // demo.setCapture && demo.setCapture(); 第一个是就执行,没有就直接跳过
// 为documnet绑定移动事件
e = e || window.e;
var c1 = e.clinetX - demo.offsetLeft;
var c2 = e.clientY - demo.offsetTop;
document.onmousemove = function(e){
e = e || window.e;
var left = e.clientX - c1;
var top = e.clientY - c2;
demo.style.left = left + "px";
demo.style.top = top +"px"
}
document.onmouseup =function(){
document.onmousemove = null;
document.onmouseup = null;
demo.relaeaseCapture(); // 松开鼠标释放出这个事件
}
提取拖拽函数
function drag(obj){
obj.onmousedown = function(e){
obj.setCapture && obj.setCapture();
e = e || window.e;
var c1 = e.clinetX - obj.offsetLeft;
var c2 = e.clientY - obj.offsetTop;
document.onmousemove = function(e){
e = e || window.e;
var left = e.clientX - c1;
var top = e.clientY - c2;
obj.style.left = left + "px";
obj.style.top = top +"px"
}
document.onmouseup =function(){
document.onmousemove = null;
document.onmouseup = null;
obj.relaeaseCapture && obj.relaeaseCapture();
}
return false;
}
}
}
var demo = document.getElementById("demo");
drag(demo); // 调用
注意:实现拖拽前样式应该设置position;
滚轮事件
需求:
- 当滚轮滚动向下滚动,demo变长
- 当滚轮向上滚动时,demo变短
- 在火狐中使用DOMMouseScroll 来绑定滚动事件
- 该事件需要通过addEventListener()函数来绑定
var demo = document.getElementById("demo");
demo.onmousewheel = function(e){
e = e || window.e
// e.wheelDelta 可以获取鼠标滚轮滚动的方向,不看大小,只看正负
// 火狐不支持 火狐支持 e.detail来获取滚动的方向 向上滚是负值
if(e.wheelDelta > 0 || e.detail < 0 ){
// 向上滚,demo变短
demo.style.height = demo.clientHeight - 10 +"px";
}else{
demo.style.height = demo.clientHeight + 10 +"px";
}
// 使用addEventListener()方法绑定响应哈数,取消默认行为时不能使用 return false 需要使用e取消默认行为
e.preventDefault(); // 和return false行为一样 ie8不能用
// 所以使用
e.preventDefault && e.preventDefault(); // 如果有这个属性就使用,没有不用
// 当滚轮滚动时,如果浏览器有滚动条,浏览器会随之滚动
// 这是浏览器默认行为 return false
return false
}
// 为火狐绑定滚轮事件
bind(demo,"DOMMouseScroll ",demo.onmousewheel);
键盘事件
键盘事件:
-
onkeydown :
-
按键被按下
-
一直按着某个按键不松手,会连续触发
-
当连续触发时,第一次和第二次间隔稍微长一点,其他都很快,为了防止误操作发生
-
-
onkeyup :
- 按键被松开
-
键盘事件一般都会绑定给一些可以获得焦点的对象或者是document
-
焦点:input中光标 失去焦点无法写数据
-
可以通过keyCode获取按键编码
-
还有几个属性
- altKey
- ctrlKey
- shiiftKey
- 这三个用来判断 alt ctrl shirft是否被同时按下
-
在文本框中输入内容,属于onkeydown的默认行为,如果 return false内容将不会出现在文本框中
document.onkeydow = function(e){
e = e || window.e;
console.log(e.keyCode);
// 判断按键被按下前需要 知道键的unicode
if(e.keyCode === 89 && e.ctrlKey){
console.log('ctrl和y都被按下');
}
}
// 是文本框中不能输入数字
<input id="demo" type="text">
<script>
var input = document.getElementById("demo");
input.onkeydown = function(e){
e = e || window.e;
if(e.keyCode >= 48 && e.keyCode <=57){
return false;
}
}
适应键盘方向键改变div
<div id="demo"></div>
<style>
width:100px;
height:100px;
background-color:red;
position:absolute;
</style>
<script>
var demo = document.getElementById("demo");
window.onload(){
document.onkeydown = function(e){
e = e || window.e;
var sp = 10;
switch(e.keyCode){
// 左
case 37:
demo.style.left = demo.offsetLft - sp + "px";
break;
// 右
case 39:
demo.style.left = demo.offsetLft + sp + "px";
break;
// 上
case 38:
demo.style.top = demo.offsetTop - sp + "px";
break;
// 下
case 40;
demo.style.top = demo.offsetTop + sp + "px";
break;
}
}
}
DOM查询元素
获取元素节点对象
-
通过document对象调用
-
使用innerHTML用于获取元素内部的html代码
-
如果想要读取元素节点属性,直接使用元素.属性名
-
document.getElementById(); // 根据id获取一个元素节点的对象 getElementsByTagName(); // 通过标签名获取一组元素节点对象 getElementsByName(); // 通过name属性获取一组元素节点对象 class属性不能采用这种读取方式 读取class属性需要用 元素.className
获取元素节点的子节点参考
- 通过具体的元素节点进行调用
- 1.getElementByTagName()
- 方法 但会当前节点的指定标签名后代节点
- childNodes
- 属性 表示当前节点的所有子节点包括文本节点
- firstChild
- 属性 表示当前节点的第一个子节点
- 通过 节点.nodevalue 可以获得值
- lastChild 表示当前节点的最后一个节点
- 属性 表示当前节点的最后一个节点
- children
- 属性 可以获取当前元素的所有元素,标签
获取父节点和兄弟节点
-
通过具体的节点调用
-
1.parentNode
- 属性,表示当前节点的父节点
-
2.previouSibling 也可能获取空白的文本 previousElementSibling;前一个元素节点
- 属性,表示当前节点的前一个兄弟节点
-
3.nextSibling
- 属性,表示当前节点的后一个兄弟节点
Dom其他方法
// 获取body标签
var body = document.getElementsByTagName("body")[0]
document.body // 获取body
document.documentElement; // html标签
document.all; // 代表页面中所有元素对象
// document.querySelector()
// ta需要一个选择器的字符串作为参数,可以根据一个css选择器来查询一个元素节点对象
document.querySelector(".box1 div"); // ta总会返回唯一的元素
document.querySelectorAll(".box1 div"); // 返回全部指定的元素,即使返回一个数据,但是也会放在数组中
Dom的增删改
appendChild(node) // 插入新的子节点
removeChild(node) // 删除子节点
var parent=document.getElementById("i1");
var child=document.getElementById("i2");
parent.removeChild(child);
子节点.parentNode.removeChild(子节点) // 自己杀自己
createElement() //创建一个新节点
createTextNode("hello") //创建一个文本节点 也就是可以看到的内容
// 例如:
var node = document.createElement("li"); // 创建一个Li标签
var content = document.createTextNode("hello"); // 创建一个hello文本
node.appendChild(content); // node节点中插入子节点
document.getElementById("ul").appendChild(node); // 再次插入到父节点中
var node = document.createElement("li"); // 创建一个Li标签
var node.innerHTML = "hello";
document.getElementById("ul").appendChild(node); // 再次插入到父节点中
getAttribute() // 返回指定的属性
<a id="de" href="http://www.baidu.com">click</a>
var link = document.getElementById('de').getAttribute('href');// 这样就可以获取链接
setAttribute() // 设置属性或修改属性的值
document.getElementsByTagName("INPUT")[0].setAttribute("type","button");
insertBefore() // 在指定的子节点前面插入新的节点 父节点进行调用
var node = document.createElement("li"); // 创建一个Li标签
var content = document.createTextNode("hello"); // 创建一个hello文本
node.appendChild(content); // node节点中插入子节点
list = document.getElementById("ul");
list.insertBefore(node,list.childNodes[0]); //插入到第一子节点的前面
replaceChild() // 替换子节点 父节点进行调动
list.replaceChild(node,list.childNodes[0]); // 使用指定的子节点,替换旧节点
<a href="javascript:;"></a> 这样点击超链接也不跳转
// 获取所有的超链接
var all = document.getElementsByTagName("a");
for(var i=0;i<all.length;i++){
all[i].onclick = function(){
// 删除之前来个提示 confirm()
var name = tr.children[0]; // 获取信息,拼接下面的删除
var flag = confirm("确认删除");// 如果点击确认返回true
if(flag){
this.parentNode.parentNode.removeChild(tr);
}
return false; // 通过响应函数最后的return false来取消点击超链接跳转的默认行为
}
}
// 将一个tr标签插入到table的过程
// 创建一个tr
var tr = document.createElement("tr");
tr.innerHTML = "<td>"++"</td>" + "<td>"++"</td>" + "<td><a href='javascript++'>+delete+"</a></td>" + "<td>"++"</td>";
var a = tr.getElementByTagName("a")[0];
a.conclick = function(){
// 删除之前来个提示 confirm()
var name = tr.children[0]; // 获取信息,拼接下面的删除
var flag = confirm("确认删除");// 如果点击确认返回true
if(flag){
this.parentNode.parentNode.removeChild(tr);
}
var table = document.getElementById("tab");
var tbody = document.getElementsByTagName("tbody")[0];
tbody.appendChild(tr);
// 深度解析
for(var i=0;i<all.length;i++){
all[i].onclick = function(){
var name = tr.children[0];
var flag = confirm("确认删除");
if(flag){
this.parentNode.parentNode.removeChild(tr);
}
return false;
}
}
// 上面代码的this转换成 all[i]会执行失败
// 因为for循环会在页面加载完成之后立即执行,而响应函数会在超链接点击之后才会执行
// 当响应函数执行时,for循环早已执行完毕
DOM操作内联样式
- 通过style属性的样式都是内联样式
- 内联样式有较高的优先级,所以通过JS修改的样式往往会立即执行
- 通过style读取也都是内联数据,无法读取样式表中的样式
- 通过currentStyle可以获取当前元素正在显示的样式,只有IE支持
- 如果当前没有样式,则获取它的默认样式
- 其他浏览器可以使用getComputedStyle()方法获取当前元素的样式window的方法 IE支持
- 该方法会返回一个对象,对象中封装了当前元素对应的样式
style{
color:red !import; //说明样式很重要,JS不能进行修改
}
// 修改样式的语法
1.先绑定一个事件
2.语法:元素.style.样式名(width,color...) = 样式值(“400px",red,...)
//读取样式
1.先绑定一个事件
2.语法:元素.style.样式名(width,color...)
// 获取当前元素正在显示的样式
语法:元素.currentStyle.样式名
// getComputedStyle()
1.要获取样式的元素
2.可以传递一个伪元素,一般为null
var a = document.getElementsByTagName("a")[0];
alert(getComputedStyle(a,null).background);
// 定义一个函数,用来获取指定元素的当前样式
function getStyle(obj,name){
return getComputedStyle(obj,null)[name];
}
alert(getStyle(a,"background"));
// 同时兼容正常浏览器和IE浏览器的方法
function getStyle(obj,name){
if(window.getComputedStyle){
return getComputedStyle(obj,null)[name];
}else{
obj.currentStyle[name];
}
}
window.getComputedStyle 和 getComputedStyle 区别
前面是window的一个属性(属性没找到则返回undefined [false])
后面则是一个变量(变量如果在全局作用域没找到则会报错)
function getStyle(obj,name){
return window.getComputedStyle?getComputedStyle(obj,null)[name]:obj.currentStyle[name];
}
// clientWidth and clientHeight 获得元素的可见宽度和高度,属性都不带px,返回都是数字 不包括边框
// 只读不能修改
var a = document.getElementsByTagName("a")[0];
alert(a.clientWidth);
// offsetWidth offsetHeight 获取元素的整个宽度和高度,包括边框
// offsetParent 可以获取当前元素的定位父元素 获取到离当前元素最近的开启定位(position)的祖先元素
// scrollLeft(获取水平滚动条滚动的距离) scrollHeight(整个滚动区域高度) scrollTop(获取垂直滚动条滚动的距离) scrollWidth整个滚动区域宽度)
overflow:auto; 出现滚动条
例子:当滚动条拖到低进行注册,阅读协议使用
scrollHeight - scrollTop == clienHeight;
// 获得一个id为info的元素,p元素的样式已经采用oveflow:auto;
var info = document.getElementById("info");
var inputs = document.getElementsTagName("input"); // input也设置成disabled
info.onscroll = function(){ // 给info绑定一个滚动事件
if(scrollHeight - scrollTop == clienHeight){
inputs[0].disabled = false;
inputs[1].disabled = false; // 这样便可以确定协议了
}
}
终于快把基础干完了,come on !!!