前端点滴(JS基础)(六)---- HTML Dom 对象操作

HTML DOM 操作

1. 属性节点的操作

(1)查询元素的属性

属性不能单独存在,一定属于一个标签。所有,操作属性,前提必须找到标签。

语法描述特点支持
元素节点.attributes获取元素的所有属性-所有浏览器
元素节点.getAttribute(属性名)获取指定属性的值标准的获取已经存在的属性值的方法所有浏览器
元素节点.属性名获取指定属性的值获取不存在的属性值时比较好用,能够获取类似于readOnly、checked等属性所有浏览器

实例:

<script>
  var input = document.getElementById('input');
  /* 元素节点.attributes */
  console.log(input.attributes);
  // NamedNodeMap {0: type, 1: id, 2: readonly, type: type, id: id, readonly: readonly, length: 3}
  console.log(input.attributes.length);  // 3
  
  /* 元素节点.getAttribute(属性名) */
  console.log(input.getAttribute('type'));  //=> text
  console.log(input.getAttribute('readOnly'));  //=> null

  /* 元素节点.属性名 */
  console.log(input.type);  //=> text
  console.log(input.readOnly);  //=> true
</script>

(2)添加/修改元素的属性

语法描述特点支持
元素节点.setAttribute(属性名,属性值)设置(添加/修改)元素的所有属性属性不存在表示添加,属性存在表示修改所有浏览器
元素节点.属性名 = 值设置(添加/修改)元素的所有属性属性不存在表示添加,属性存在表示修改所有浏览器

实例:

/* 设置元素属性 */
  input.setAttribute("value","yaodao");
  input.value = "yaodao"
  
/* 修改元素属性 */
  input.setAttribute("name","text2");
  input.name = "text2"

效果:
(设置前):
在这里插入图片描述
(设置后):
在这里插入图片描述

(3)删除元素的属性

/* 删除元素属性 */
  input.removeAttribute("value")

在这里插入图片描述

(4)判断元素是否有哪个属性

语法:标签节点.hasAttribute("属性名")

注意: 返回Boolean类型的值。

/* 判断是否存在元素属性 */
  console.log(input.hasAttribute("value"));  //=> false
  console.log(input.hasAttribute("name"));  //=> true

总结

元素节点的增删改查:

  • 增:document.creatElement(“标签名”); document.creatTextNode(“文本”); 父节点.appendChild(子节点); 父节点.insertBefore(新节点,参照节点)
  • 删:父节点.removeChild(子节点);
  • 改:父节点.replaceChild(新节点,参照节点)
  • 查:document.getElementById(“元素id”); document.getElementsByTagName(“标签名”); document.getElementsByClassName(“类名”);document.getElementsByName(“元素的name属性”);document.querySelector(“css选择器”);document.querySelectorAll(“css选择器”)

属性节点的增删改查:

  • 增:元素节点.setAttribute(“属性名”,“属性值”); 元素节点.属性名 = “属性值”;
  • 删:元素节点.removeAttribute(“属性名”);
  • 改:元素节点.setAttribute(“属性名”,“属性值”); 元素节点.属性名 = “属性值”;
  • 查:元素节点.attributes; 元素节点.getAttribute(“属性名”); 元素节点.属性名;

2. DOM 对象的通用属性

innerHTML

  • 获取/设置元素里的html内容

innerText

  • 获取/设置元素里面的文本内容

nodeName

  • nodeName 是只读的

    元素节点的 nodeName 与标签名相同
    ​属性节点的 nodeName 与属性名相同
    ​文本节点的 nodeName 始终是 #text
    ​文档节点的 nodeName 始终是 #document

nodeValue

  • 元素节点的 nodeValue 是 undefined 或 null
  • 文本节点的 nodeValue 是文本本身
  • 属性节点的 nodeValue 是属性值

nodeType
调用nodeType属性会得到一个数字,这个数字表示节点的类型

  • 元素 1
  • 属性 2
  • 文本 3
  • 注释 8
  • 文档 9

实例:

<script type="text/javascript">
  var p = document.getElementById('p');

//innerHTML,innerText
  /* 获取元素里的html内容 */
  console.log(p.innerHTML);   //=> 123<span>456</span>
  /* 获取元素里的文本内容 */
  console.log(p.innerText);   //=> 123456

  /* 设置元素中的html内容 */
  p.innerHTML = '<a href="#">按钮</a>';
  /* 设置元素里的文本内容 */
  p.innerText = '这是innerText后的文本';

// nodeName
  /* 获取元素节点的nodeName */
  console.log(p.nodeName);  //=> p
  /* 获取属性节点的nodeName */
  console.log(p.getAttributeNode("id").nodeName);  //=> id

// nodeValue
  /* 获取元素节点的nodeValue */
  console.log(p.nodeValue); //=> undefined
  console.log(p.getAttributeNode("id").nodeValue);  //=> p

// nodeType
  /* 获取元素节点的nodeType */
  console.log(p.nodeType);  //=> 1
  /* 获取属性节点的nodeType */
  console.log(p.getAttributeNode("id").nodeType);  //=> 2
  /* 获取文本节点的nodeType */  
  console.log(p.childNodes[0].nodeType);  //=> 3
  /* 获取文档的nodeType */
  console.log(document.nodeType);  //=> 9
</script>

3. 设置/获取元素的css样式

(1)设置样式

语法: elementNode.style.css样式 = 值

css样式的写法:
①、一个单词的直接写即可。比如color height …
②、样式名称带中横线的,去掉中横线,后面单词首字母大写。比如fontSize lineHeight backgroundColor

实例:
在这里插入图片描述

(2)获取样式

使用 " elementNode.style.样式名称" 的方式只能获取行内样式和js已经设置过的样式。
要想获取全部的样式,则必须使用下面的方法:

  • 在IE中支持 elementNode.currentStyle.样式名称
  • 火狐支持 getComputedStyle(elementNode).样式

为了兼容各个浏览器,所以需要自己封装一个函数,用于获取完整的css样式:

function getStyle(el,style){
	// IE 支持类型
	if(el.currentStyle){
		return el.currentStyle[style]
	}else{
	// 火狐支持类型
		return getComputedStyle(el)[style]
	}
}
console.log(getStyle(p,'fontSize'))

调用 getStyle() 获取完整的样式。

注意: 样式名有需要地使用驼峰命名法,并且以字符串的方式参入参数。

4. DOM获取元素的位置

静态元素位置属性:

  • offsetLeft 元素在网页中水平坐标值
  • offsetTop 元素在网页中垂直坐标值
  • offsetWidth 元素在页面中占据的宽度
  • offsetHeight 元素在页面中占据的高度
    在这里插入图片描述
    注意: 当前offsetWidth = width+padding+border。
    注意: 当前offsetLeft = margin-left。
    注意: 当前offsetTop = margin-top。

动态元素位置属性:

  • scrollLeft 滚动条在容器中水平滚动的距离,多用于浏览器的滚动条
  • scrollTop 滚动条在容器中垂直滚动的距离,多用于浏览器的滚动条
    在这里插入图片描述
    间歇滚动实现案例:
// <ul id="Dong"> 关键是css中设置 overflow:hidden;
	var Dong = document.getElementById("Dong");
	Dong.innerHTML += Dong.innerHTML;  
	var iLiHeight = 45;				//设置滚动行高
	Dong.scrollTop = 0;		//初始化
	var tim;																		
	function moving() {
		Dong.scrollTop++;							
		tim = setInterval(scrollUp, 30);
	}							
	function scrollUp() {
		if (Dong.scrollTop % iLiHeight ==0) {
			clearInterval(tim);										
			setTimeout(moving, 3000)
		}																		
		else {
			Dong.scrollTop++;								
			if (Dong.scrollTop >= Dong.scrollHeight/2) {
				Dong.scrollTop =0;        	
			}
		}
	}
	setTimeout(moving,3000); 		
})

5. 事件和事件对象

(1)什么是事件

浏览网页时,当我们做出点击鼠标、按键盘、移动鼠标等行为时,这些行为会被浏览器内置的JavaScript引擎所捕获,并执行对应的某些操作(函数)。那么你的行为(动作)+ JavaScript引擎捕获 + 执行对应的操作 = 事件
所以,一个完整的事件应该包括:

  • 用户行为;
  • 浏览器捕获你的行为;
  • 执行对应的操作(函数)

常见行为有:鼠标点击、鼠标的移动、鼠标的移入和移出、键盘控制等等。
事件的作用是:通过事件,我们(浏览网页的人)就可以和浏览器进行一些交互了。

(2)事件绑定的多种方式

声明: 如果同时存在标签事件,DOM方法绑定的事件。优先执行DOM方式绑定的事件。

1、on() 绑定事件

语法:elementNode.on('不带on的常用事件名',function(){})

实例:

document.getElementById('btn').on('click', function () {
    alert(123);
});
2、事件名绑定事件

语法:elementNode.带有on的常用事件名 = function(){}

实例:

document.getElementById('btn').onclick = function () {
    alert(123);
};
3、事件监听绑定事件

事件监听的方法有两种:

  • addEventListener——兼容:firefox、chrome、IE、safari、opera;不兼容IE7、IE8
  • attachEvent——兼容:IE7、IE8;不兼容firefox、chrome、IE9、IE10、IE11、safari、opera

addEventListener() 语法: elementNode.addEventListener(event, function, useCapture)

注意: useCapture (可选)布尔值,指定事件是否在捕获或冒泡阶段执行。【true:事件句柄在捕获阶段执行; false:默认,事件句柄在冒泡阶段执行】,需要了解事件发生过程:事件捕获----处于目标----事件冒泡

attachEvent() 语法: elementNode.attachEvent(event, function)

共性与区别:

相同点:
  都是dom对象的方法,可以实现一种事件绑定多个事件处理函数。
  
不同点:

  1. attachEvent是IE有的方法,它不遵循W3C标准,而其他的主流浏览器如FF等遵循W3C标准的浏览器都使用addEventListener,所以实际开发中需分开处理。

  2. 多次绑定后执行的顺序是不一样的,attachEvent是后绑定先执行(覆盖),addEventListener是先绑定先执行(不会覆盖)。

  3. 存在兼容问题,绑定事件名方法不同,addEventListener() 方法的event参数不用带on ,attachEvent() 方法中的event 参数需要带on。

同样为了兼容各个浏览器,所以需要自己封装一个函数,用于监听事件:

var btn = document.getElementById('btn');
function listenFn(el,type,fn){
	if(window.addEventListener){
			return el.addEventListener(type,fn);
	}else{
			return el.attachEvent('on'+type,fn)
	}
};
function fn(){
	alert(123);
};
function fn2(){
	alert(456);
};
// ...
listenFn(btn,'click',fn);
listenFn(btn,'click',fn2);
// ... 还可以绑定多个事件

效果:
在这里插入图片描述
事件监听的第三个参数说明:
addEventListener第三个参数涉及到的事件捕获与冒泡。

 <style>
    #div1{
      width: 200px;
      height: 200px;
      background-color: red;
    }
    #div2{
      width: 100px;
      height: 100px;
      background-color: green;
    }
  </style>
  
<div id="div1" >
    <div id="div2">
      <button id="btn">按钮</button>
    </div>
</div>
  
<script type="text/javascript">
window.onload=function(){
  document.getElementById("btn").addEventListener("click",function () {
  // body...
    alert("hello");
  });
  document.getElementById("div2").addEventListener("click",function(){
    alert("div2");
  },true);
  document.getElementById("div1").addEventListener("click",function(){
    alert("div1");
  });
}
</script>

效果:
在这里插入图片描述
说明:

  • 默认情况下addEventListener() 的第三个参数为false/不填,表示元素触发事件在冒泡阶段 事件流:btn事件 -> div2事件 -> div1事件。

当处于目标div2 时元素触发事件,事件就会逐层向上冒泡 div1事件 -> div2事件;当处于目标btn 时元素触发事件,事件同样会逐层向上冒泡div1事件 -> div2事件 -> btn事件。

  • 非默认情况下addEventListener() 的第三个参数为true,表示元素触发事件在捕获阶段 事件流:div1事件 -> div2事件 -> btn事件。

当处于目标div2 时元素触发事件,事件会根据捕获阶段的事件流,先触发div2事件,再经过冒泡阶段触发div1事件。当处于目标btn 时,由于div2 addEventListener() 的第三个参数为true,在捕获阶段触发。所以先触发div2事件,再触发btn事件,最后触发div1事件。

  • 不过要注意一点:不要因为捕获而忽略冒泡。
4、标签中绑定事件

直接在标签中添加事件,例如:
<input type="button" value="按钮" id="btn" onclick="fn2()">

function fn2(){
   alert(456);
}
5、实例说明
<input type="text" id="username" value="请输入用户名" />
<script>
//找到username,绑定获取焦点事件
    document.getElementById('username').onfocus = function () {
        document.getElementById('username').value = '';
    };
 //优化
    document.getElementById('username').onfocus = function () {
        this.value = '';
    };
</script>

在事件处理函数中,this表示绑定事件的那个元素

HTML代码:

<!- 要求:页面中有很多个td,点击td的时候,让td的背景颜色发生变化  ->
<table>
    <tr>
        <td></td>
        <td></td>
        <td></td>
    </tr>
    <tr>
        <td></td>
        <td></td>
        <td></td>
    </tr>
</table>

css代码:

<style>
    table,td{
        border:solid 1px #ccc;
        border-collapse: collapse; /*合并边框*/
    }
    td{
        width:150px;
        height:50px;
    }
    table{
        margin:10px auto; /*让表格左右居中对齐*/
    }
</style>

JS代码:

<script>
    //点击页面中的td,点击之后,让被点击的td背景颜色改变成随机颜色
    //先找到所有的td
    var tds = document.getElementsByTagName('td'); // 返回数组
    //循环,为每个td都绑定一个单击事件
    for(var i=0; i<tds.length; i++){
        tds[i].onclick = function () {
            //this 表示绑定事件的那个td
            var r = Math.floor(Math.random()*256);
            var g = Math.floor(Math.random()*256);
            var b = Math.floor(Math.random()*256);
            this.style.backgroundColor = 'rgb('+r+', '+g+', '+b+')';
            //全变红色
            /*if(this.style.backgroundColor != 'red'){
                this.style.backgroundColor = 'red';
            }else{
                this.style.backgroundColor = 'white';
            }*/
        };
    }
</script>

效果:
在这里插入图片描述

(3)常用的事件名

  1. 页面事件:
  • onload :当页面载入完毕(页面中的标签和外部资源)后触发
  1. 焦点事件:
  • onfocus :当获取焦点时触发
  • onblur :当失去焦点时触发
  1. 鼠标事件:
  • onmouseover :当鼠标悬浮时触发
  • onmouseout :当鼠标离开时触发
  1. 键盘事件:
  • onkeypress :当键盘按下时触发(如果按住某个键不松开,会一直触发press事件)
  • onkeydown :当键盘按下时触发
  • onkeyup :当键盘弹起时触发
  1. 其他事件:
  • onchange :内容改变时会触发,常用于select>option。
  • onsubmit :表单提交时触发,这个事件要给form绑定而不是给提交按钮绑定
  • onresize : 页面窗口改变大小时会触发
  • onscroll :滚动条滚动时触发

(4)什么是事件对象

事件对象也是一个对象,它提供了一些属性,这些属性描述了当前事件的特点;
不同的事件中,事件对象也有所差异,比如单击事件中,事件对象会提供pageX和pageY属性,表示点击的点距离页面的距离,比如键盘事件中,事件对象会提供keyCode属性,表示按的是什么键。
总之,事件对象中提供了一些属性,这些属性可以很好的描述当前的事件的特点。

(5)获取事件对象

IE 浏览器:window.event;
主流浏览器:传递给事件函数的参数。

同样的为了兼容各个浏览器,兼容各个浏览器的获取事件对象的方法:

 document.getElementsByTagName('input')[0].onclick = function(a){
	if(window.event){
		e = window.event;
	}else{
		e = a;
	}
	// 简写
	var e = window.event||a;
}

(6)事件对象的常用属性

下面列举一些事件对象中的常用属性:

  • target:返回触发此事件的元素(事件的目标节点)。
  • currentTarget:返回其事件监听器触发该事件的元素。
  • keyCode:表示键盘上的键对应的数值。
  • altKey:表示是否按了alt键,按了结果为true,没按结果为false(组合按键的时候,才会有作用)
  • shiftKey:表示是否按了shift键,按了结果为true,没按结果为false(组合按键的时候,才会有作用)
  • ctrlKey:表示是否按了ctrl键,按了结果为true,没按结果为false(组合按键的时候,才会有作用)
  • pageX: 鼠标距离页面左边的距离
  • pageY: 鼠标距离页面上面的距离
  • screenX: 鼠标距离屏幕左边的距离
  • screenY: 鼠标距离屏幕上面的距离

实例:
在这里插入图片描述

(7)事件对象的方法

stopPropagation() 阻止冒泡事件的发生。
1. 什么是冒泡事件?

在这里插入图片描述
上述小例子中,点击元素的子元素,会透过子元素触发元素本身的事件,这就是冒泡事件。

首先,要清楚什么是事件流?
事件流:
当一个HTML元素产生一个事件时,该事件会在元素节点与根节点之间的路径传播,路径所经过的节点都会收到该事件,这个传播的过程叫做DOM事件流。
元素触发事件时,事件的传播过程称为事件流,过程分为捕获和冒泡两种:

冒泡事件: 微软提出的 事件由子元素传递到父元素的过程,叫做冒泡
捕获事件: 网景提出的 事件由父元素到子元素传递的过程,叫做事件捕获

有些时候要的就是这个效果,可以不做任何处理;有些时候不希望有冒泡事件发生,那么可以通过事件对象的方法来阻止冒泡的发生。

2. 阻止冒泡事件的发生

阻止冒泡事件的发生有:

  • 标准浏览器使用 evt.stopPropagation(); //evt指的是事件对象
  • IE内核浏览器使用 window.event.cancelBubble = true;

可以封装一个兼容各个浏览器的阻止冒泡的方法:

<script>

    /*************** 阻止冒泡函数 *************/
    function zuzhi(evt){
        if(window.event){
            window.event.cancelBubble = true;
        }else{
            evt.stopPropagation(); //evt指的是事件对象
        }
    }

    //分别给两个div绑定单击事件
    document.getElementById('d1').onclick = function () {
        alert(11111);
    };
    document.getElementById('d2').onclick = function (evt) {
        alert(22222);
        //阻止冒泡发生
        zuzhi(evt);  // 此处会阻止11111的弹出
    };
</script>
preventDefault() 阻止标签的默认行为。

默认行为就是html标签的一些默认行为,比如点击a标签会跳转,比如点击了submit按钮表单会提交。这些都属于标签的默认行为。
有些时候,点击了a标签或者submit按钮后不希望执行标签的默认行为,这时候就需要阻止默认行为。
阻止默认行为:
标准浏览器:evt.preventDefault();
IE内核浏览器:window.event.returnValue = false;

兼容各个浏览器的阻止标签默认行为的方法:

<body>
<a href="13冒泡事件.html">跳转</a>
<form name="f1" action="07全选.html" method="post">
    用户名:<input type="text" name="username"><br>
    密 码:<input type="password" name="pwd"><br>
    <input type="submit" id="sub" value="提交">
</form>
<script>
    /********* 阻止标签的默认行为 *********/
    //形参evt标签标准浏览器的事件对象
    function zuzhi(evt){
        if(window.event){
            //IE浏览器
            window.event.returnValue = false;
        }else{
            //非IE浏览器
            evt.preventDefault();
        }
    }
    document.getElementById('sub').onclick = function (evt) {
        //检测用户名是否为空
        if(document.f1.username.value == ''){
            alert('用户名不能为空');
            //阻止表单提交
            zuzhi(evt);
            //return false; //return false也可以阻止表单提交
        }
    };
</script>

注意: return false 同样可以阻止默认行为。

综合案例----可编辑表格

HTML:

<table>
    <thead>
    <tr>
        <th>ID</th>
        <th>姓名</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>1</td>
        <td>唐僧</td>
    </tr>
    <tr>
        <td>2</td>
        <td>悟空</td>
    </tr>
    <tr>
        <td>3</td>
        <td>八戒</td>
    </tr>
    <tr>
        <td>4</td>
        <td>沙僧</td>
    </tr>
    <tr>
        <td>5</td>
        <td>白龙马</td>
    </tr>
    <tr>
        <td>6</td>
        <td>金箍棒</td>
    </tr>
    </tbody>
</table>

css:

<style>
        *{
            margin:0;
            padding:0;
            border:0 none;
        }
        table,th,td{
            border:solid 1px #1b272e;
            border-collapse: collapse; /*合并边框*/
        }
        table{
            width:400px;
            margin:10px auto; /*左右居中对齐*/
        }
        th,td{
            width:50%;
            padding:3px;
        }
</style>

js:

/* 要求:隔行换色,姓名可修改,且点击姓名后自动变成 value为原有值的 input 并且宽高与 td 一致,绑定回车与esc键盘事件 */

//兼容各个浏览器的获取完整css样式的写法
    function getStyle(node, styleName){
        if(node.currentStyle){
            //说明是IE
            return node.currentStyle[styleName];
        }else{
            return getComputedStyle(node)[styleName];
        }
    }
// 隔行换色
// 找到所有的 tr 进行遍历,如果遍历的 i 能够整除2,就改变颜色。
var trs = document.querySelectorAll('tbody tr');
for(var i = 0;i<trs.length;i++){
	if(i%2 == 0){
		trs[i].style.backgroundColor = '#d4d4d4';
	}
}
//获取姓名td
var tds = document.querySelectorAll('tbody td:nth-child(2n)');
//循环遍历给每个姓名td绑定单击事件
for(var i = 0;i<tds.length;i++){
	tds[i].onclick = function(){
		//将每一个td赋值给变量td进行操作,避免改变原有数据
		var td = this;   //this表示点击事件的对象td[i]
		var text = td.innerText;
		td.innerHTML = '';
		//创建input框
		var input = document.createElement('input');
		//设置样式
		input.style.width = getStyle(td,"width");
		input.style.height = getStyle(td,"height");
		input.style.backgroundColor = getStyle(td,"backgroundColor");
		input.style.fontSize = getStyle(td,"fontSize");
		input.style.outline= "none";
		//将保存的td文本赋值给input.value
		input.value = text;
		//在td中加入设置好的input框 
		td.appendChild(input);
		//获取焦点
		input.focus();

		//绑定键盘事件,enter成功设置,esc取消设置(恢复原形)。
          input.onkeyup = function (evt) {
                var e = window.event||evt;
                var keyCode = e.keyCode;
                if(keyCode == 13){ //表示按了回车,表示确定
                    td.innerHTML = ''; //先清空td中的input
                    td.innerHTML = this.value;
                }
                if(keyCode == 27){ //按ESC键表示取消
                    td.innerHTML = ''; //先清空td中的input
                    td.innerHTML = text;
                }
            };
	}
}

效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值