javaScript快速入门之宿主对象(DOM)

宿主对象(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
      • 一般不会这样使用

浏览器加载顺序是从上到下执行

  • 如果将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 !!!

猜你喜欢

转载自blog.csdn.net/qq_42992704/article/details/105074712
今日推荐