20、DOM的基本操作

DOM的基本操作

文章目录

什么是DOM

DOM是一套方法和集合的统称

1.DOM—> Document Object Model

DOM、BOM等一切系统生成的成组的方式,基本上全是类数组。

2.DOM定义了表示和修改文档所需的方法。

DOM对象即为宿主对象,由浏览器厂商定义,用来操作html和xml功能的一类对象的集合(DOM不能操作css)。也有人称DOM是对HTML以及XML的标准编程接口。

xml是html之前的版本 xml ---- xhtml ---- html

xml中可以自定义标签,以前传数据都是xml,现在被json替代了。

// 自定义标签可以作为属性名 内容就是属性值
<student>
    <name>老邓</name>
    <age>100</age>
</student>

1.对节点的增删改查

查看元素节点

document代表整个文档
// document单独写就代表整个文档的js显示形式  
//整个文档啥意思呢 可以理解为html标签的上一级  包含所有内容
document.getElementByld()

元素id在ie8以下的浏览器,不区分id大小写,而且也返回匹配name属性的元素,所以ie8以下的浏览器写name="only"也会被选出来。用得很少!!!id选择器尽量不用。

// 通过id查找元素  选出的是整个id对应的内容部分
<div id="only"></div>
<script type="text/javascript">
// id和元素是一一对应的  所以一个id只能选一个元素 所以这里element是单数
	var div = document.getElementById('only');
</script>
getElementsByTagName()

通过标签名选择元素,最主流的用法。

// 通过标签名把标签选出来,选出来之后封装到一个类数组中,所有的标签通过类数组的索引位排序
<div id="only"></div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div');
     // 拿出div后是一个数组 可以随意操作
     // div.length;
	// div[1].innerHTML=123;

</script>
// 选div中的p标签
<div>
    <p></p>
</div>
<p></p>
<script type="text/javascript">
	var p = document.getElementsByTagName('p')[0]; //0就是第一个p标签
</script>
var div = document.getElementsByTagName('div')[0]; // 选出第一个div
// 通过DOM修改div属性
div.style.width = "100px";
div.style.height = "100px";
div.style.backgroundcolor = "red";

// 点击次数为奇数时绿色  偶数时红色
var conut = 0;
div.onclick = function () { // 一旦发生点击事件,将会执行后面的函数
    count ++;
    if(count % 2 == 1) {
        this.style.backgroundcolor = "green";  // 谁调用的this,this就指向谁
    }else {
        this.style.backgroundcolor = "red";
    }
}
getElementsByName()

需注意,只有部分标签name可生效(表单,表单元素,img,iframe)

// 但凡是elements的都是选出后封装成类数组(除了id之外其他都是)
<input name="fruit"></input>
<script type="text/javascript">
	var div = document.getElementsByName('fruit');
</script>
getElementsByClassName()

类名->ie8和ie8以下的ie版本中没有,可以多个class一起

// 注意 页面中哪怕只有一个demo 但是选出来的只有一个也是以数组的形式展示 所以要拿某个特定的demo还是需要加下标
<div>
    <p class="demo"></p>
</div>
<p></p>
<script type="text/javascript">
	var p = document.getElementsByTagName('demo')[0];
</script>
querySelector()

css选择器在ie7和ie7以下的版本中没有,querySelector不常用,因为它选出的数据不是实时的。

<div>
	<strong></strong>
<div>
	<span>
		<strong class="demo">123</strong>
	</span>
</div>
<script type="text/javascript">
// css中怎么选择元素这里就怎么选 因为它识别的就是css > 是直接下级元素
// 注意这里选出的是一个  不是一组
	var strong = document.querySelector('div > span strong.demo');
</script>
querySelectorAll()

css选择器在ie7和ie7以下的版本中没有,querySelectorAll不常用,因为它选出的数据不是实时的

<div>
	<strong></strong>
<div>
	<span>
		<strong class="demo">123</strong>
	</span>
</div>
<script type="text/javascript">
// 注意这里选出的是一组 只有一个也是以数组的形式展示
	var strong1 = document.querySelectorAll('div > span strong.demo');
</script>
//  querySelectorAll()是静态的
<div></div>
<div class="demo"></div>
<div></div>
<script type="text/javascript">
// 一开始选择三个标签之后就不改了  哪怕div.remove()把那个元素删了也还是存在这个div中  就好比当时拷贝了一个副本 但是后来更新也不会发生改变
    var div = document.querySelectorAll('div');
</script>

遍历节点树:

<div>
	<span></span>
	<div>
		<p></p>
	</div>
</div>
			div(父节点)
span(左孩子)				div(右孩子)
							p(叶子结点)
parentNode —–>父节点

最顶端的parentNode为#document,一个元素只有一个父节点。

<div>
	<strong></strong>
	<span></span>
	<em></em>
</div>
<script type="text/ javascript">
    // 通过parentNode可以查找到当前元素的父节点  
    // 一直找上去会发现顶层是document 而document没爹
	var strong = document.getElementsByTagName('strong')[0];
</script>

image-20221009211603779

childNodes —–>子节点们

一个元素的子节点有若干个

<div>
	<strong>
    	<span>1</span>
    </strong>
	<span></span>
	<em></em>
</div>
<script type="text/ javascript">
    // 通过childNodes可以查找到当前元素的子节点
    // 注意:strong中的span节点时孙子节点  子节点是下一层节点
	var strong = document.getElementsByTagName('div')[0];
	// div.childNodes.length  返回长度是7  因为空白文本节点也算(标签与标签之间的空格 div和strong之间  strong和span之间  span和em之间  em和div之间)
</script>
<div>
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// div.childNodes.length  返回长度是7 也就是div.childNodes类数组中有七个元素四个文本节点  一个注释节点  一个strong节点  一个span节点
</script>
<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// div.childNodes.length  返回长度还是7   123也是文本  只不过之前是空文本  现在有内容 
</script>
firstChild —–>第一个子节点
<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// div.firstChild 返回第一个子节点 文本节点“  123 ”
</script>
lastChild —–>最后一个子节点
<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// div.lastChild 返回最后一个子节点 空文本节点#text
</script>
nextSibling —–>后一个兄弟节点
<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var strong = document.getElementsByTagName('strong')[0];
	// div.nextSibling 返回后一个兄弟节点 空文本节点#text
</script>

image-20221010053556968

previousSibling —–>前一个兄弟节点
<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var strong = document.getElementsByTagName('strong')[0];
	// div.previousSibling 返回前一个兄弟节点 空文本节点#text
</script>

基于元素节点树的遍历

不包含文本节点和注释节点。除了children以外,都是ie9以下不兼容。

parentElement —–>返回当前元素的父元素节点

(IE不兼容)

<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// div.parentElement 返回当前元素的父元素节点body
</script>

html的元素父节点是null 因为document不是元素节点,是文本节点。

image-20221010054029547

children —–>只返回当前元素的元素子节点
<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// div.children 返回当前元素的元素子节点 strong、span
</script>
node.childElementCount === node.children.length

当前元素节点的子元素节点个数(IE不兼容)

<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// div.childElementCount 返回当前元素的元素子节点个数 和div.children.length一样
</script>
firstElementChild —–>返回的是第一个元素节点

(IE不兼容)

<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// div.firstElementChild 返回当前元素的第一个子节点 strong
</script>
lastElementChild —–>返回的是最后一个元素节点

(IE不兼容)

<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// div.firstElementChild 返回当前元素的最后一个子节点 span
</script>
nextElementSibling—–>返回后一个兄弟元素节点

(IE不兼容)

<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
	<em></em>
    <i></i>
    <b></b>
</div>
<script type="text/javascript">
	var strong = document.getElementsByTagName('strong')[0];
	// div.nextElementSibling 返回后一个兄弟元素节点span
</script>

image-20221010055129348

previousElementSibling –>返回前一个兄弟元素节点

(IE不兼容)

<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
	<em></em>
    <i></i>
    <b></b>
</div>
<script type="text/javascript">
	var span = document.getElementsByTagName('span')[0];
	// div.previousElementSibling 返回前一个兄弟元素节点span
</script>

节点的四个属性

nodeName

元素的标签名,以大写形式表示(非注释和文本元素节点),只读不可写

<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
	<em></em>
    <i></i>
    <b></b>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div');
</script>
// 上面代码访问div.firstChild.nodeName第一个子元素的标签名
// 返回"#text"

// 访问div.ChildNodes[1].nodeName  返回第2个子元素的标签名
// 返回“#comment”

// 访问div.ChildNodes[3].nodeName  返回第4个子元素的标签名
// 返回“STRONG”
nodeValue

Text节点或Comment节点的文本内容,可读写

<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
	<em></em>
    <i></i>
    <b></b>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div');
</script>

// 可以修改注释或文本节点的内容

image-20221010060831443

image-20221010060913744

nodeType 获取节点类型

该节点的类型,只读不可写,每一个节点都有一个nodeType属性

节点的类型
元素节点——1
属性节点——2
文本节点——3
注释节点——8
document——9
DocumentFragment——11
<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
	<em></em>
    <i></i>
    <b></b>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div');
</script>
// 访问document.nodeType  返回9

// div.childNodes[1].nodeType 第二个子元素节点是注释节点
// 返回8

// div.childNodes[0].nodeType 第一个子元素节点是文本节点
// 返回3

// div.childNodes[3].nodeType 第四个子元素节点是strong节点
// 返回1 元素节点

image-20221010061619745

image-20221010061706675

// 把div下面的元素节点全挑出来放到数组中返回
<div>
    123
    <!-- This is comment -->
    <strong></strong>
    <span></span>
	<em></em>
    <i></i>
    <b></b>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div');
	// 封装方法 传一个node就把对应的子元素全返回(不能用children)
	// 思路:全部遍历一遍  把nodeType为1(元素节点)的全部放进数组中
	function retElementChild(node) {
        var arr =[];
        child = node.childNodes;
        len = child.length;
        for( var i = 0; i < len, i ++) {
            // 返回类型为1的部分放进数组中
            if(child[i].nodeType === 1) {
                arr.push(child[i]);
            }
        }
        return arr;  // 返回数组
    }
</script>


// 高级写法
	function retElementChild(node) {
        var temp ={
            length :0;
            push : Array.prototype.push,
            // 加上这个属性 让对象变得像数组
            splice : Array.prototype.splice 
        };
        child = node.childNodes;
        len = child.length;
        for( var i = 0; i < len, i ++) {
            if(child[i].nodeType === 1) {
                temp.push(child[i]);
            }
        }
        return temp;
    }

temp对象形式展示

image-20221010063004257

temp数组形式展示

image-20221010063223730

attributes

Element节点的属性集合,属性名不可以改,属性值可以改。基本不用!

// 属性节点结合 d="only" class="demo"这两个是属性
<div id="only" class="demo"></div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div');
	// 访问div.attributes 返回对应元素的属性集合
</script>

image-20221010064310697

节点的一个方法Node.hasChildNodes();

<div id="only" class="demo">
    <span></span>
</div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	// hasChildNodes() 判断是否有子节点(包含注释和文本) 返回true和false  div中span删除了也还有子节点(文本分割字节) 除非<div></div> 这样两个div挨着  没有文本字节了就返回false
</script>

image-20221010064734723

DOM结构树

代表一系列继承关系!!!

Document应该还有一个分支XMLDocument,Element也应该还有一个分支XMLElement

Node也是一个构造函数,是结构树的最顶端。

image-20221010200205019

document和Document的区别

document返回的是整个文档,大的Document返回的是构造函数(因为构造函数的函数名才要求首字母大写),但是这个构造函数比较特殊,不能new它,这是系统留给自己的!

image-20221010200443843

document、Document和HTMLDocument的联系

大的Document是小的document的构造函数的原型,所以大的Document加一个abc属性,通过小的document能访问出来。

image-20221010200933895

document --> HTMLDocument document的构造函数是HTMLDocument

原型继承关系:

document --> HTMLDocument.prototype --> Document.prototype

// 因为document的构造函数时HTMLDocument
// 所以document的原型是 HTMLDocument.prototype
// 而HTMLDocument的原型又是Document.prototype

HTMLDocument.prototype = {
    __proto__ : Document.prototype;
}

继承遵循就近原则

image-20221010202144581

HTMLElement

如果在HTMLElement上定义方法,那所有下级的元素都可以使用

HTMLHeadElement

head标签能使用 HTMLHeadElement上定义的方法

HTMLHeadElement.prototype.abc='demo';
var head = document.getElementsByTagName ('head')[0];
head.abc;

image-20221010203516025

HTMLBodyElement

body标签能使用 HTMLBodyElement上定义的方法

HTMLBodyElement.prototype.abc='demo';
var body = document.getElementsByTagName ('body')[0];
body.abc;

image-20221010203247178

找原型最顶端
document.__proto__ // 返回HTMLDocument{...}
document.__proto__.__proto__ // 返回Document{...}
document.__proto__.__proto__.__proto__ // Node{...}
document.__proto__.__proto__.__proto__.__proto__ // 事件
document.__proto__.__proto__.__proto__.__proto__.__proto__ // 返回Object.prototype
document.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__ // 返回null

image-20221010204225392

DOM基本结构

1.getElementByld方法定义在Document.prototype上,即Element节点上不能使用。

getElementByld --> Document.prototype
// 所以无论是XMLDocument还是HTMLDocument上都能用 所以跟Document并行的节点(Element等)不能使用

2.getElementsByName方法定义在HTMLDocument.prototype上,即非html中的document不能使用(XMLDocument,Element)

getElementsByName --> HTMLDocument.prototype
// 所以XMLDocument(平级)或者Element等不相干的节点不可使用

3.getElementsByTagName方法定义在Document.prototype和Element.prototype上

getElementsByTagName --> Document.prototype
getElementsByTagName --> Element.prototype
// 所以无论是XMLDocument还是HTMLDocument上以及Element包含的部分HTMLElement/XMLElement以及包含的部分都能用 所以getElementsByTagName比较灵活

<div>
	<span>1</span>
</div>
<span></span>
<script type="text/javascript">
    // div和span都属于element 所以都可以调用getElementsByTagName这个方法
	var div = document.getElementsByTagName('div')[0];
	var span = div.getElementsByTagName('span')[0];
	// 写*就是把所有的标签都选出来了
	var div = document.getElementsByTagName('*')[0];
</script>

image-20221010205759380

4.HTMLDocument.prototype定义了一些常用的属性,body,head,分别指代HTML文档中的<body><head>标签。

document.body --> body  // document中的body就是body标签
document.head --> head  // document中的head就是head标签

image-20221010210406725

5.Document.prototype上定义了documentElement属性,指代文档的根元素,在HTML文档中,他总是指代<html>元素

// document中的documentElement就是html标签
document.documentElement --> html

image-20221010210439073

6.getElementsByClassName、querySelectorAll、querySelector在Document.prototype,Element.prototype类中均有定义

getElementsByClassName、querySelectorAll、querySelector --> Document.prototype
getElementsByClassName、querySelectorAll、querySelector --> Element.prototype

// 所以无论是XMLDocument还是HTMLDocument上以及Element包含的部分HTMLElement/XMLElement以及包含的部分都能用

课堂练习

1.遍历元素节点树(在原型链上编程)

// 方法一:给你一个父节点 然后遍历所有子节点

// 已知树形结构,把层级结构打印出来(分层打印出来)
<div>
	<p></p>
	<span>
		<strong></strong>
		<b></b>
	</span>
</div>

2.封装函数,返回元素e的第n层祖先元素节点

<div>
	<strong>
		<span>
			<i></i>
		</span>
	</strong>
</div>
<script type="text/javascript">
    var i = document.getElementsByTagName('i')[0];
    // 第一个参数是元素 第二个是num(也就是第几个父级)
    function retParent(elem, n) { 
        // 加elem是因为null没父级 所以elem为null时退出循环
        while(elem && n) {
             // 把elem的父级赋值给elem
            elem = elem.paentElement; 
            n--;  // n(父级)有多少个就循环多少圈
        }
    	return elem;
    }
</script>

// 访问retParent(i,1)  返回span
// 访问retParent(i,2)  返回strong
// 访问retParent(i,3)  返回div
// 访问retParent(i,10)  报错 没那么多父级 所以条件加elem

3.封装函数,返回元素e的第n个兄弟元素节点,n为正,返回后面的兄弟元素节点,n为负,返回前面的,n为0,返回自己。

<div>
	<span></span>
	<p></p>
	<strong></ strong>
	<i></i>
	<address></ address>

</div>
<script type="text/javascript">
    var strong = document.getElementsByTagName('strong')[0];
    // 第一个参数是元素 第二个是num(也就是第几个兄弟)
    function retSibling(e, n) { 
        // 加e是因为null没兄弟 所以e为null时退出循环
        while(e && n) { 
             // 把e的兄弟赋值给elem
            if(n > 0) {
                e = e.nextElementSibling; 
                // n --是因为返回后面的兄弟节点了 所以-1
                n --; 
            }else {
                e = e.priviousElementSibling; 
                // n ++是因为返回前面的兄弟节点了 所以+1
                n ++;
            }
        }
        // n为0,返回自己。不用处理
    	return e;
    }
</script>

// 不通过nextElementSibling和priviousElementSibling方法
    function retSibling(e, n) { 
        while(e && n) { 
            if(n > 0) {
                if(e.nextElementSibling) { // 还能用就用
                    e = e.nextElementSibling;
                else {
                    // for循环可以不加执行体 一直到下个节点时元素节点  e为nu会报错ll 所以e也加入判断条件
                    for(e = e.nextSibling;e && e.nodeType != 1; e = e.nextSibling;)
                	}
                }
                n --; 
            }else {
                if(e = e.priviousElementSibling;) {
                    e = e.priviousElementSibling; 
                }else {
                    for(e = e.priviousSibling;e && e.nodeType != 1; e = e.priviousSibling;)
                }
                n ++;
            }
        }
    	return e;
    }

4.编辑函数,封装myChildren功能,解决以前部分浏览器的兼容性问题

<div>
	<b></b>
	abc
	<!-- this is comment -->
     <strong>
		<span>
			<i></i>
		</span>
	</strong>
</div>
<script type="text/javascript">
    // 考点就是怎么区分元素节点和非元素节点
    Element.prototype.myChildren = function () {
        var child = this.childNodes;
        var len = child.length;
        var arr = [];
        for(var i =0; i< len; i ++){
            if(child[i].nodeType == 1){
                arr. push(child[i]) ;
            }
        }
        return arr;
    }
	var div = document.getElementsByTagName('div')[0];
</script>

// 访问div.myCildren() 返回[b, strong]

image-20221010220124916

5.自己封装hasChildren()方法,不可用children属性

// 判断有没有子元素(空文本和注释不算的那种)
<div>
	<b></b>
	abc
	<!-- this is comment -->
     <strong>
		<span>
			<i></i>
		</span>
	</strong>
</div>
<script type="text/javascript">
	function hasChildren() {
        var child = this.childNodes;
        var len = child.length;
        for(var i =0; i< len; i ++){
            if(child[i].nodeType == 1){
                return true;
            }
        }
        return false;
    }
	var div = document.getElementsByTagName('div')[0];
</script>

增加元素节点

document.createElement();常见

创建元素节点

// 创建一个div标签  并且返回到div变量中(也就是代表div标签)
var div = document.caeateElement('div');

// 创建好之后 往容器中加入创建的div
document.body,appendChild(div)

// 修改div
div.innerHTML = 123
document.createTextNode();

创建文本节点

var text = document.createTextNode('张杰很帅!!!');
document.createComment();

创建注释节点

var comment = document.createComment('This is comment!');
document.createDocumentFragment();

插入元素节点

ParentNode.appendChild();常见

任何一个元素节点都有appendChild()方法,可以直接理解成push

创建完的东西插入已知的东西

<div></div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	var text = document.createTextNode('张杰很帅!!!');
	var span = document.caeateElement('span');
	// div调用appendChild方法把text放入div中
	div.appendChild(text); 
	// span出现在text后面
	div.appendChild(span); 
	var text1 = document.createTextNode('demo');
	// 往span中添加text1
	span.appendChild(text1); 
</script>

把已知的,已经在页面中的东西插入到另一个东西中,没问题,所以说明appendChild相当于剪切操作。

<div></div>
<script type="text/javascript">
    // 试试就会发现没毛病,所以appendChild相当于剪切操作。
	span.appendChild(text); 
</script>
<div></div>
<span></span>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
	var span = document.getElementsByTagName('span')[0];
	div.appendChild(span);  // 把span标签插入div标签中
</script>

image-20221011062327523

ParentNode.insertBefore(a, b);常见

一定要父级调用,往父级自己内部插入东西,可以理解为在b之前插入a。

<div>
    <span></span>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
	var span = document.getElementsByTagName('span')[0];
    var strong = document.caeateElement('strong');
    var i = document.caeateElement('i');
	// 在span之前往div中插入strong标签
	div.insertBefore(strong, span);
	// 把i标签插入strong之前
	div.insertBefore(i, strong)
</script>

删除元素节点

parent.removeChild();

谋杀:父节点删除自己的子节点,removeChild是剪切操作。

<div>
    <span></span>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
	var span = document.getElementsByTagName('span')[0];
    var strong = document.caeateElement('strong');
    var i = document.caeateElement('i');
	div.insertBefore(strong, span);
	div.insertBefore(i, strong)
</script>

// 父节点很删除子节点i标签
div.removeChild(i);

// i标签赋值给ii
var ii = div.removeChild(i);
// 访问ii  返回<i></i> 说明remove是剪切操作

父节点删除i标签

image-20221011064447747

删除后的i标签赋值给ii (证明removeChild是剪切操作)

image-20221011065121158

child.remove();常见

自杀:子节点自己调用remove()方法自尽,remove直接删除。

<div>
    <span></span>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
	var span = document.getElementsByTagName('span')[0];
    var strong = document.caeateElement('strong');
    var i = document.caeateElement('i');
	div.insertBefore(strong, span);
	div.insertBefore(i, strong)
</script>

// 子节点自己删除i标签
i.remove();

image-20221011065333656

替换

parent.replaceChild(new, origin);

拿新的元素去替换老的元素。

<div>
    <span></span>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
	var span = document.getElementsByTagName('span')[0];
    var strong = document.caeateElement('strong');
    var i = document.caeateElement('i');
	div.insertBefore(strong, span);
	div.insertBefore(i, strong);
    var p = document.caeateElement('p');
</script>

// 用p替换strong
div.replaceChild(p, strong)

替换前的div

image-20221011065841159

p替换strong后

image-20221011070010117

Element节点的一些属性

innerHTML

改变标签内的内容,inner操作赋值都会覆盖内容 除了用+=

<div>
    <span>123</span>
	<strong>234</strong>
</div>
<script type="text/javascript">
     var div = document.getElementsByTagName('div')[0];
</script>

// div.innerHTML  这样写是获取div中的内容
// div.innerHTML = '123'  这样写是覆盖div中的内容(这里把div内的span和strong都覆盖了)
// div.innerHTML += '456' // 在123后追加456

div.innerHTML内容获取和覆盖

image-20221011203030017

div.innerHTML += 操作

image-20221011203222958往innerHTML中写html结构都是可以识别的

image-20221011203413545

innerText(火狐不兼容)/ textContent(老版本IE不好使)
<div>
    <span>123</span>
	<strong>234</strong>
</div>
<script type="text/javascript">
     var div = document.getElementsByTagName('div')[0];
</script>

div.innerText 获取所有标签文本内容。因为火狐不兼容innerText,所以火狐有一个功能一样的方法textContent。

image-20221011203645392

image-20221011203909510

div.innerText = '123'赋值会把div中的内容全部覆盖

image-20221011204258284

image-20221011204313049

div.textContent获取内容

image-20221011204545980

Element节点的一些方法

ele.setAttribute()

给元素设置行间属性,前面是属性名,后面是属性值。列如:div.setAttribute('class','demo');

<div>
    <span>123</span>
	<strong>234</strong>
</div>
<script type="text/javascript">
     var div = document.getElementsByTagName('div')[0];
</script>

div.setAttribute('class','demo');

image-20221011204853683

div.setAttribute('id','only');

image-20221011205101459

ele.getAttribute();

获取元素属性值:div.getAttribute('id') 获取id的属性值only

<div>
    <span>123</span>
	<strong>234</strong>
</div>
<script type="text/javascript">
     var div = document.getElementsByTagName('div')[0];
</script>

image-20221011205139745

练习:取data-log(打点)

// 记录一个a标签被点击了多少次
<div>
	<a href="#"data-log="0">hehe</a>
</div>
<script type="text/javascript">
     var div = document.getElementsByTagName('div')[0];
     var a = document.getElementsByTagName('a')[0];
	a.onclick = function () {
        // 点击一次就会打印一次
        console.log(this.getAttribute('data-log'));
    }
</script>

练习: 给所有标签分别加上属性和属性值

<div></div>
<span></span>
<strong></strong>
<script type="text/javascript">
    var all = document.getElementsByTagName('*');
    for(var i = 0; i < all.length; i ++) {
        all[i].setAttribute('this-name',all[i].nodeName);
    }
</script>

image-20221011210549869

课堂练习

请编写一段JavaScript脚本生成下面这段DOM结构,并且插入到页面中去。要求:使用标准的DOM方法或属性。

<div class="example">
	<p class="slogan">最帅!</p>
</div>
<script type="text/javascript">
    var div = document.caeateElement('div');
    var p = document.caeateElement('p');
    div.setAttribute('class', 'example');
    p.setAttribute('class', 'slogan');
    //p.innerText += '张杰最帅!';  这个和下面的都可以插文本
	var text = document.createTextNode('最帅!')
    // appendChild插入元素节点
     p.appendChild(text); // 在p中插入text
	div.appendChild(p); // 往div中插入p标签
	// 把div插入到body中,也就是写入到页面中去
     document.body.appendChild(div);
</script>

image-20221011221041587

提示 dom.className可以读写class

dom.className = '';
dom.id = '';

课后作业

1.封装函数insertAfter();功能类似insertBefore()
提示:可忽略老版本浏览器,直接在Element.prototype上编程

直接在原型链上变成的好处是this可以指代任何一个想调用的对象!!!

// 假如要放一个元素到b标签之后  其实就是span标签之前  也就是下一个兄弟元素标签之前 如果是最后一位  直接appendChild
<div>
    <i></i>
	<b></b>
	<span></span>
</div>
<script type="text/javascript">
	Element.prototype.insertAfter = function (targetNode, afterNode) {
    	// 定义afterNode的下一个兄弟元素之前就是要放入的位置
        var beforeNode = afterNode.nextElementsiling;
    	if(beforeNode == null) {
        // 没有兄弟节点时直接插入targetNode this指待插入元素
            this.appendChild(targetNode);
        }else {
            // 在beforeNode之前插入targetNode
       		this.inserBefore(targetNode, beforeNode)
        }
    }
	var div = document.getElementsByTagName('div')[0];
     var b = document.getElementsByTagName('b')[0];
     var span = document.getElementsByTagName('span')[0];
     var p = document.createElement('p');
</script>

div.insertAfter(p, b); 在b标签之后加入p标签。

image-20221011223900064

2.将目标节点内部的节点顺序逆序。

例如:
<div><a></a><em></em></div>
<div><em></em><a></a></div>
// 把b标签剪切到span标签之后 再把i标签剪切到b标签之后
<div>
    <i></i>
	<b></b>
	<span></span>
</div>
<script type="text/javascript">
    Element.prototype.nx = function () {
    	var div = document.getElementsByTagName('div')[0];
        var children = div.children;
        var len = children.length;
        for(i = 0; i < len; i ++) {
            if(children[i] !== div.lastElementSibling) {
				div.appendChild(this.previousElementSibling);
            }else {
                
            }
        }
</script>

获取窗口属性

查看滚动条的滚动距离

window.pageXoffset/page.Yoffset

IE8及IE8以下不兼容(下面的那种方法就是IE8及以下的版本用来查看滚动条滚动距离的)

// window.pageXoffset 求x轴滚动距离
// window.pageYoffset 求y轴滚动距离
document.body/documentElement.scrollLeft/scrollTop

兼容性比较混乱,用时取两个值相加,因为不可能存在两个同时有值。

// document.body.scrollLeft
// document.body.scrollTop

// documentElement.scrollLeft
// documentElement.scrollTop

document.body方法如果有值ocumentElement就会没值,ocumentElement方法如果有值ocumentElement就会没值document.body,所以用的时候取两个值相加。

image-20221013210245184

封装兼容性方法,求滚动轮滚动离getScrollOffset()
function getScroll0ffset() {
    if (window.pageXoffset) {
    	return {
              x : window.pageXoffset,
			y : window.pageYoffset
    	}
    }else{
        return {
        x : document.body.scrollLeft + document.doc
        umentElement.scrollLeft,
        y : document.body.scrollTop + document.doc
        umentElement.scrollTop
        }
    }
}

查看视口的尺寸

编写的网页的可见部分宽高,不包含浏览器头部地址栏和标签栏!

window.innerWidth/innerHeight
// window.innerWidth  1440是标准宽度
// window.innerHeight

IE8及IE8以下不兼容

image-20221013212708339

document.documentElement.clientWidth/clientHeight

标准模式下,任意浏览器都兼容

// html第一行加了<!DOCTYPE html>就是标准模式
// document.documentElement.clientWidth
// document.documentElement.clientHeight
document.body.clientWidth/clientHeight

适用于怪异/混杂模式下的浏览器,可以兼容老版本的代码

// html第一行没有<!DOCTYPE html>就是怪异模式
// document.body.clientWidth
//  document.body.clientHeight
封装兼容性方法,返回浏览器视口尺寸getViewportOffset()

document.compatMode查模式

标准模式返回CSS1Compat

image-20221013213010271

怪异模式返回BackCompat 向后兼容

image-20221013213135274

function getViewportOffset(){
    if(window.innerWidth) {
        return {
       		w : window.innerwidth,
             h : window.innerHeight
        }
	}else{
        if(document.compatMode === "BackCompat") {
            return {
            	w : document.body.clientwidth,
                 h : document.body.clientHeight
            }
        }else{
            return {
                w : document.documentElement.clientwidth,
                h : document.documentElement.clientHeight
            }
    }
}

获取Dom尺寸

查看元素的几何尺寸

domEle.getBoundingClientRect();
//  domEle.getBoundingClientRect();
<div style="width : 100px; height : 100px; background-
color:red ; position:absolute; left:100px;top:100px">
</div>
var div = document.getElementsByTagName('div')[0];

// left/right/top/bottom是左右上下四个点的坐标
div.getBoundingClientRect() 

image-20221013214234499

兼容性很好

该方法返回一个对象,对象里面有left,top,right,bottom等属性。left和top代表该元素左上角的X和Y坐标, right和bottom代表元素右下角的X和Y坐标

height和width属性老版本IE并未实现

返回的结果并不是“实时的"

查看元素的尺寸

dom.offsetWidth,dom.offsetlleight
 // dom.offsetWidth  获取元素宽度(盒子宽度 所以还要看padding和border)
 // dom.offsetlleight 获取元素高度(盒子高度 所以还要看padding和border)

查看元素的位置

dom.offsetLeft, dom.offsetTop

注意:offsetLeft求的是元素距离他有定位的父级的距离。不管是left、right还是margin隔出来的距离都是返回这个距离。没有有定位的父级时才是相对文档的距离。

 // dom.offsetLeft
 // dom.offsetTop

特点:对于无定位父级的元素,返回相对文档的坐标。对于有定位父级的元素,返回相对于最近的有定位的父级的坐标。

dom.offsetParent

返回最近的有定位的父级,如无,返回body,body.offsetParent返回null

1

让滚动条滚动

window上有三个方法
scroll(),scrollTo() scrollBy();

scroll(), scrollTo()功能一模一样,但是这个滚动距离只会滚动一次,到位置就停了

// scroll(0,100)  第一个是x坐标  第二个是y坐标 y轴滚动条移到100px处

// scrollTo(0,100)  第一个是x坐标  第二个是y坐标 y轴滚动条移到100px处

image-20221013220537869

scrollBy()是累加滚动

// scrollBy(0,100) 执行一次滑动100像素 再执行一次  继续滑动

image-20221013220915405

三个方法功能类似,用法都是将x,y坐标传入。即实现让滚动轮滚动到当前位置。

区别:scrollBy()会在之前的数据基础之上做累加。

eg:利用scrollBy()快速阅读的功能

<div style="width:100px;height:100px;background-color:orange;color:#fff; font-size:40px; font-weight:bold;text-align: center;line-height: 100px; position:fixed ; bottom:200px; right: 50px; border-radius :50%;opacity:0.5;">start
</div>
<div style="width: 100px; height :100px; background-color:#0f0;color:#fff; font-size:40px;font-weight: bold;textalign: center;line-height : 100px;position:fixed ; bottom:50px; right:50px; border-radius :50%;opacity:0.5; ">stop
</div>
<script type="text/javascript">
    var start = document.getElementsByTagName('div'[0];
    var stop = document.getElementsByTagName('div'[1];
	var timer = 0;
	var key = true;
    start.onclick = function () {// 0.1秒滚动10像素
        // 这里速度会累加 因为产生了多个定时器 所以要加锁key
        if(key) {
            timer = setInterval( function () {
                // 100可以写成变量 自定义速度
                window.scrollBy(0,100); 
                clearInterval(timer);
        	},100);
            key = false;
        }
    }
	stop.onclick = function () {  // 暂停
            clearInterval(timer);
        	key = true;
    	}
    }
</script>

脚本化CSS

Dom不能直接操作css,但是可以间接操作css

读写元素css属性

dom.style.prop
<div style="float:left;width:100px;height:100px; background-color:red;"></div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
</script>

// div.style 会展示所有这个div能用的css属性  标红的是我们使用的
// 属性名是数字(索引位)的属性和其他正常的属性在同一个对象中就是类数组

image-20221014054441654

间接的修改css属性

image-20221014054833763

可读写行间样式(行间样式就是定义在标签中的style=“width:100px”),没有兼容性问题,碰到float这样的保留字属性,前面应加css

// 假如把行间样式中的width去掉  style中定义  那宽度也是200  但是dom.style.width会打印空  因为这不是行间样式  无法读写
// 再添加dom.style.width=“200px"时  width就更改了
<style type="text/ css">
    div{
  	  width: 200px;
    }
</style>

eg:float — > cssFloat

// 直接写float也行  但是因为是保留字  所以最好加css

image-20221014060709745

复合属性必须拆解

// border:"1px solid #ccc";  // 这种复合属性最好拆解

image-20221014061042725

组合单词变成小驼峰式写法

// 比如background-color  因为js无法识别- 只认数字字符下划线和$
// background-color  --> backgroundColor

写入的值必须是字符串格式

// backgroundColor:yellow  --> backgroundColr = "yellow"

image-20221014055542906

没值的属性也可以添加值

div.style.borderRadius = "50%"

image-20221014055847502

查询计算样式

window.getComputedStyle(ele,null);
获取伪元素

null是获取伪元素的

/*给div添加伪类*/
div::after {
        content: "";
        width: 50px;
        height: 50px;
        background-color: green;
        display: inline-block;
    }

/*获取伪类宽度*/
window.getComputedStyle(div,"after").width

image-20221014065309288

点击红色方块时 伪元素(绿色部分)变黄色

// 点击时更换样式
<div class="green" style="float:left;width:10em;height:100px; background-color:red;">
    </div>
    <script type="text/javascript">
        var div = document.getElementsByTagName('div')[0];
        div.onclick = function () {
            div.className = "yellow"
        }
    </script>
<style>
    .green::after {
        content: "";
        width: 50px;
        height: 50px;
        background-color: green;
        display: inline-block;
    }
    .yellow::after {
        content: "";
        width: 50px;
        height: 50px;
        background-color: yellow;
    }
</style>

image-20221014070520075

获取当前元素展示出的一切css属性值(包括默认值)
//  window.getComputedStyle(div,null);

image-20221014062630087

image-20221014062745572

对象就可以.属性,这里获取的是所有的属性 不只是行间样式 也包含style中定义的属性 这个比div.style更准一些 因为这个是所有的样式

image-20221014062859716

计算样式只读

写入报错,样式是计算过的,就好比系统默认背景色是灰色 你定义背景黄色 最后出来的是混合之后的绿色 或者在行间和非行间中定义两个权重一样的宽度 一个200 一个300 最后计算出来就是250

image-20221014063245675

返回的计算样式的值都是绝对值,没有相对单位

比如把width改成相对单位,会返回计算后的值,颜色返回rgba展示形式

 <div style="float:left;width:10em;height:100px; background-color:red;">
</div>

image-20221014063839415

IE8及 IE8以下不兼容,所以用以下方法

查询样式(了解就好 都淘汰了)

  1. ele.currenStyle
  2. 计算样式只读
  3. 返回的计算样式的值不是经过转换的绝对值
  4. IE独有的属性

image-20221014064202530

封装兼容性方法getStyle(elem,prop);
function getstyle(elem, prop) {
    if(window.getComputedStyle) {
        return window.getComputedStyle(elem,null)[prop];
    }else{
        return elem.currentStyle[prop];
    }
}
通过点击改变div的宽高并修改背景色
div {
	width: 100px;
     height: 100px;
	background-color: red;
}
.active {
    width: 200px;
    height: 200px;
	background-color: green;
}
.green::after {
        content: "";
        width: 50px;
        height: 50px;
        background-color: green;
        display: inline-block;
    }
    .yellow::after {
        content: "";
        width: 50px;
        height: 50px;
        background-color: yellow;
    }
var div = document.getElementsByTagName('div')[0];
div.onclick = function () {
    // 方法一 改类(效率高、好维护)
     div.className = "active";
    // 方法二 直接修改(效率低、不好维护)
     div.style.width = "200px";
     div.style.height = "200px";
	div.style.backgroundColor = "green";
}

小练习:让方块儿移动

<div style="width: 100px;height:100px ; background-color: red ; position:absolute;left:0;top:0;"></div>
<script type="text/javascript">
    function getStyle(elem, prop) {
        if(window.getComputedStyle) {
        	return window.getComputedStyle(elem,null)[prop];
   		}else{
       	 	return elem.currentStyle[prop];
        }
    }
    var div = document.getElementsByTagName('div ')[0];
	var speed = 2;
	var timer = setInterval (function() {
        speed += speed/7;
   		div.style.left = parseInt(getstyle(div,'left')) + speed + ' px ';
    },10 );
	if(parseInt(getstyle(div,'left') > 500) {
       clearInterval(timer);
       }
</script>

兼容,所以用以下方法`

查询样式(了解就好 都淘汰了)

  1. ele.currenStyle
  2. 计算样式只读
  3. 返回的计算样式的值不是经过转换的绝对值
  4. IE独有的属性

[外链图片转存中…(img-pqZWtLxN-1665755178158)]

封装兼容性方法getStyle(elem,prop);
function getstyle(elem, prop) {
    if(window.getComputedStyle) {
        return window.getComputedStyle(elem,null)[prop];
    }else{
        return elem.currentStyle[prop];
    }
}
通过点击改变div的宽高并修改背景色
div {
	width: 100px;
     height: 100px;
	background-color: red;
}
.active {
    width: 200px;
    height: 200px;
	background-color: green;
}
.green::after {
        content: "";
        width: 50px;
        height: 50px;
        background-color: green;
        display: inline-block;
    }
    .yellow::after {
        content: "";
        width: 50px;
        height: 50px;
        background-color: yellow;
    }
var div = document.getElementsByTagName('div')[0];
div.onclick = function () {
    // 方法一 改类(效率高、好维护)
     div.className = "active";
    // 方法二 直接修改(效率低、不好维护)
     div.style.width = "200px";
     div.style.height = "200px";
	div.style.backgroundColor = "green";
}

小练习:让方块儿移动

<div style="width: 100px;height:100px ; background-color: red ; position:absolute;left:0;top:0;"></div>
<script type="text/javascript">
    function getStyle(elem, prop) {
        if(window.getComputedStyle) {
        	return window.getComputedStyle(elem,null)[prop];
   		}else{
       	 	return elem.currentStyle[prop];
        }
    }
    var div = document.getElementsByTagName('div ')[0];
	var speed = 2;
	var timer = setInterval (function() {
        speed += speed/7;
   		div.style.left = parseInt(getstyle(div,'left')) + speed + ' px ';
    },10 );
	if(parseInt(getstyle(div,'left') > 500) {
       clearInterval(timer);
       }
</script>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好好学习_fighting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值