js DOM


DOM

Dom Node NodeList NodeCollection基本讲解

dom&node

  • (文档对象模型)Document Object Model
  • 注意 DOM最小组成单位叫做节点 Node

常见的Node有elementtextattributecommentdocument等(所以要注意节点元素的区别,元素属于节点的一种)。

Node关系

Node类型

节点 类型 nodeName nodeType 含义
Document Node.DOCUMENT_NODE #document 9 文档节点 整个文档(window.document)
Element ELEMENT_NODE 大写的 HTML 元素名 1 元素节点 HTML元素(比如、等)
Attribute ATTRIBUTE_NODE 等同于 Attr.name 2 属性节点 HTML元素的属性(比如 class=”right”)
Text TEXT_NODE #text 3 文本节点 HTML 文档中出现的文本
DocumentType DOCUMENT_TYPE_NODE 等同于 DocumentType.name 10 文档类型节点 文档的类型(比如)
DocumentFragment DOCUMENT_FRAGMENT_NODE #document-fragment 11 文档碎片节点 文档的片段

验证例子

document.nodeName // "#document"
document.nodeType // 9
document.querySelector('a').nodeType === 1 // true
document.querySelector('a').nodeType === Node.ELEMENT_NODE // true

nodeList

NodeList 对象是一个节点的集合,一般由Node.childNodesdocument.getElementsByNamedocument.querySelectorAll返回的。

不过需要注意,Node.childNodesdocument.getElementsByName返回的NodeList的结果是实时的(此时跟HTMLCollection比较类似),而document.querySelectorAll返回的结果是固定的,这一点比较特殊。

NodeList 接口提供 length 属性和数字索引,因此可以像数组那样,使用数字索引取出每个节点,但是它本身并不是数组,不能使用 pop 或 push 之类数组特有的方法。当然可以转成数组。

NodeList 部署了 Iterator 接口,因此还可以用 for…of 进行遍历。

var childNodes = document.body.childNodes;
console.log(childNodes.length); // 如果假设结果是“2”
document.body.appendChild(document.createElement('div'));
console.log(childNodes.length); // 此时的输出是“3”

HTMLCollection

HTMLCollection是一个特殊的NodeList,表示包含了若干元素(元素顺序为文档流中的顺序)的通用集合,它是实时更新的,当其所包含的元素发生改变时,它会自动更新。另外,它是一个伪数组,如果想像数组一样操作它们需要像Array.prototype.slice.call(nodeList, 2)这样调用。

所以实际上针对不同的元素 有不同调用方法属性。 分为node HTML元素 document element text

getElementsByTagName() 方法返回 HTMLCollection 对象。

var x = document.getElementsByTagName("p");
y = x[1];//获取集合中的第二个p元素

length 属性定义了 HTMLCollection 中元素的数量

var myCollection = document.getElementsByTagName("p");
document.getElementById("demo").innerHTML = myCollection.length;
//另一个实际利用
var myCollection = document.getElementsByTagName("p");
var i;
for (i = 0; i < myCollection.length; i++) {
    myCollection[i].style.backgroundColor = "red";
}

HTMLCollection 并非数组!

HTMLCollection 与 NodeList 的区别

  • HTMLCollection是 HTML 元素的集合。
  • NodeList 是文档节点的集合。
  • NodeList 和 HTML 集合几乎完全相同。
  • HTMLCollection 和 NodeList 对象都是类数组的对象列表(集合)。
  • 它们都有定义列表(集合)中项目数的 length 属性。
  • 它们都可以通过索引 (0, 1, 2, 3, 4, …) 像数组那样访问每个项目。
  • 访问 HTMLCollection 项目,可以通过它们的名称、id 或索引号。
  • 访问 NodeList 项目,只能通过它们的索引号。
  • 只有 NodeList 对象能包含属性节点和文本节点。
  • 节点列表不是数组!
  • 节点数组看起来像数组,但并不是。
  • 您能够遍历节点列表并像数组那样引用其节点。
  • 不过,您无法对节点列表使用数组方法,比如 valueOf()、push()、pop() 或 join()。

HTMLCollection vs. NodeList

节点查找API

document.getElementById :根据ID查找元素,大小写敏感,如果有多个结果,只返回第一个;

document.getElementsByClassName :根据类名查找元素,多个类名用空格分隔,返回一个 HTMLCollection 。注意兼容性为IE9+(含)。另外,不仅仅是document,其它元素也支持 getElementsByClassName 方法;

document.getElementsByTagName :根据标签查找元素, * 表示查询所有标签,返回一个 HTMLCollection

document.getElementsByName :根据元素的name属性查找,返回一个 NodeList 。

document.querySelector :返回单个Node,IE8+(含),如果匹配到多个结果,只返回第一个。

document.querySelector(“#app”) //获取到id名为app的首个元素

document.querySelector(“.app”) //获取到class名为app的首个元素

document.querySelectorAll :返回一个 NodeList ,IE8+(含)。

document.forms :获取当前页面所有form,返回一个 HTMLCollection ;

深入理解如何使用querySelector

<div id="opo">
    <span>
        <p>
            <i>1</i>
        </p>
        <p class="p">
            <b>
                <input type="text" name="tel">
                <input type="text" name="age">
            </b>
        </p>
    </span>
</div>
<script>
//querySelector
let c = document.querySelector('#opo');//CSS语法查找节点
let c1 = document.querySelector('div span .p b input[name=age]');//他可以像css一样去选择
console.log(c1)

//querySelectorAll
let d = document.querySelectorAll('#opo span p');//跟getElementsByTagName很相似,获取当前选择的所有标签
d.forEach((item,index)=>{//也可以循环})
</script> 
<div id="my-id">
        <img id="inside">
        <div class="lonely"></div>
        <div class="outer">
            <div class="inner"></div>
        </div>
    </div>
<script>
document.querySelectorAll("div")//返回页面中所有div元素组成的节点列表(NodeList类型的对象)
document.querySelector("div.lonely")//返回一个单独的div元素。
document.querySelector("#my-id").querySelectorAll("img")//会查找#my-id下的图片子代元素(注意是子代而不是后代    
</script>
//这下面两个是一样的意思嘛?
document.querySelectorAll("#my-id div div");//实际上只有一个
document.querySelector("#my-id").querySelectorAll("div div");//实际上三个 div.lonely,div.outer,div.inner
//第一个是查询一个被#my-div下div包裹的div元素
//另一个是查询一个被div包裹的div元素,而这个div是#my-id的子代元素

4、Element.insertAdjacentElement()

<p>
  <!-- afterbegin -->
  foo
  <!-- beforeend -->
</p>
<!-- afterend -->

用法和上面类似,

targetElement.insertAdjacentElement(position, element);

5、removeChild

removeChild用于删除指定的子节点并返回子节点,语法:

var deletedChild = parent.removeChild(node);  

deletedChild指向被删除节点的引用,它仍然存在于内存中,可以对其进行下一步操作。另外,如果被删除的节点不是其子节点,则将会报错。一般删除节点都是这么删的:

function removeNode(node)  
{  
    if(!node) return;  
    if(node.parentNode) node.parentNode.removeChild(node);  
}  

6、replaceChild

replaceChild用于将一个节点替换另一个节点,语法:

parent.replaceChild(newChild, oldChild);  

节点关系API

1、父关系API

parentNode :每个节点都有一个parentNode属性,它表示元素的父节点。Element的父节点可能是Element,Document或DocumentFragment;

parentElement :返回元素的父元素节点,与parentNode的区别在于,其父节点必须是一个Element元素,如果不是,则返回null;

2、子关系API

children :返回一个实时的 HTMLCollection ,子节点都是Element,IE9以下浏览器不支持;

childNodes :返回一个实时的 NodeList ,表示元素的子节点列表,注意子节点可能包含文本节点、注释节点等;

firstChild :返回第一个子节点,不存在返回null,与之相对应的还有一个 firstElementChild ;

lastChild :返回最后一个子节点,不存在返回null,与之相对应的还有一个 lastElementChild ;

childElementCount :返回子元素节点的个数,相当于children.length

3、兄弟关系型API

previousSibling :节点的前一个节点,如果不存在则返回null。注意有可能拿到的节点是文本节点或注释节点,与预期的不符,要进行处理一下。

nextSibling :节点的后一个节点,如果不存在则返回null。注意有可能拿到的节点是文本节点,与预期的不符,要进行处理一下。

previousElementSibling :返回前一个元素节点,前一个节点必须是Element,注意IE9以下浏览器不支持。

nextElementSibling :返回后一个元素节点,后一个节点必须是Element,注意IE9以下浏览器不支持。

4、包含关系查询

hasChildNodes(): 在包含一个或多个子节点时返回true,比查询childNodes列表的length属性更简单

contains() :接受一个节点作为参数,返回一个布尔值,表示参数节点是否为当前节点的后代节点。参数为后代节点即可,不一定是第一层子节点 

元素属性型API

1、setAttribute 给元素设置属性:

element.setAttribute(name, value);  

其中name是特性名,value是特性值。如果元素不包含该特性,则会创建该特性并赋值。

2、getAttribute

getAttribute返回指定的特性名相应的特性值,如果不存在,则返回null:

var value = element.getAttribute("id"); 

3、hasAttribute

var result = element.hasAttribute(name);

var foo = document.getElementById("foo"); 
if (foo.hasAttribute("bar")) { 
    // do something
}

4、dataset

获取html data-开头的属性,用法如下:

<div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth>John Doe</div>

let el = document.querySelector('#user');

// el.id == 'user'
// el.dataset.id === '1234567890'
// el.dataset.user === 'johndoe'
// el.dataset.dateOfBirth === ''

el.dataset.dateOfBirth = '1960-10-03'; // set the DOB.

// 'someDataAttr' in el.dataset === false
el.dataset.someDataAttr = 'mydata';
// 'someDataAttr' in el.dataset === true

样式相关API

1、直接修改元素的样式

elem.style.color = 'red';  
elem.style.setProperty('font-size', '16px');  
elem.style.removeProperty('color');  

2、动态添加样式规则

var style = document.createElement('style');  
style.innerHTML = 'body{color:red} #top:hover{background-color: red;color: white;}';  
document.head.appendChild(style);  

3、classList获取样式class

// div is an object reference to a <div> element with class="foo bar"
div.classList.remove("foo");
div.classList.add("anotherclass");

// if visible is set remove it, otherwise add it
div.classList.toggle("visible");

// add/remove visible, depending on test conditional, i less than 10
div.classList.toggle("visible", i < 10 );

alert(div.classList.contains("foo"));

// add or remove multiple classes
div.classList.add("foo", "bar", "baz");
div.classList.remove("foo", "bar", "baz");

// add or remove multiple classes using spread syntax
let cls = ["foo", "bar"];
div.classList.add(...cls); 
div.classList.remove(...cls);

// replace class "foo" with class "bar"
div.classList.replace("foo", "bar");

4、window.getComputedStyle

通过 element.sytle.xxx 只能获取到内联样式,借助 window.getComputedStyle 可以获取应用到元素上的所有样式,IE8或更低版本不支持此方法。

var style = window.getComputedStyle(element[, pseudoElt]);  

获取相关高度API

getBoundingClientRect

getBoundingClientRect 用来返回元素的大小以及相对于浏览器可视窗口的位置,用法如下:

var clientRect = element.getBoundingClientRect();  

clientRect是一个 DOMRect 对象,包含width、height、left、top、right、bottom,它是相对于窗口顶部而不是文档顶部,滚动页面时它们的值是会发生变化的。

DOM交互事件

基本事件总结表

当id中string中有数字,需要自己增加; 直接number++;(不用转换)

但是如果用number+=1/ number=number+1; 这样要praseInt(number)

DOM 事件监听程序

语法

element.addEventListener(event, function, useCapture);

第一个参数是事件的类型(比如 “click” 或 “mousedown”)。

(注意:事件名称前不加on; 使用内联onclick属性似乎只能传递自身而不能传递事件对象; 事件监听可以在一种事件上绑定多个方法)

第二个参数是当事件发生时我们需要调用的函数。

第三个参数是布尔值,指定使用事件冒泡还是事件捕获。此参数是可选的。

注意:请勿对事件使用 “on” 前缀;请使用 “click” 代替 “onclick”。

添加单个或者多个监听

//单个元素单个事件
element.addEventListener("click", function(){ alert("Hello World!"); });
//单个元素
element.addEventListener("click", myFunction);
element.addEventListener("click", mySecondFunction);
//单个元素多个不同事件
element.addEventListener("mouseover", myFunction);
element.addEventListener("click", mySecondFunction);
element.addEventListener("mouseout", myThirdFunction);
//自定义
element.addEventListener("resize", function(){
    document.getElementById("demo").innerHTML = sometext;
});
//有参数
element.addEventListener("click", function(){ myFunction(p1, p2); });

删除事件监听

element.removeEventListener("mousemove", myFunction);
var x = document.getElementById("myBtn");
x.addEventListener("mouseover", myFunction); 
x.removeEventListener("mouseover", myFunction); 
function myFunction() {
  document.getElementById("demo").innerHTML += "Moused over!<br>"
}

解除绑定不能写全函数

解除绑定事件的时候一定要用函数的句柄,把整个函数写上是无法解除绑定的。

错误写法:

btn.addEventListener("click",function(){
 alert(11);
});
btn.removeEventListener("click",function(){
 alert(11);
});
正确写法:

btn.addEventListener("click",eventTwo);
btn.removeEventListener("click",eventOne);

事件对象

事件对象自动传递给回调函数 element.onclick = function(e){}; // e就是事件对象

注意: 注意listener的对象, this 是指拥有listener的对象,但是event.target是当时的event

e的常见属性:

  • e.target; //获取触发此事件的元素(不一定是绑定元素)(e.target.style.backgroundColor=””)
  • e.currentTarget //获取触发此事件的元素(一定是绑定元素)
  • e.offsetX ||e.offsetY ; //获取鼠标基于target元素内部的偏移x和y
  • e.clientX ||e.clientY ; //获取鼠标基于浏览器视窗的偏移x和y
  • e.keyCode ||e.which; //返回键盘上的字符的代码
  • 事件回调中的this:指向事件的触发元素
  • —-如果事件处理函数的绑定在元素生成之前,则此元素不能绑定事件处理函数,需重新设置

target、this、currentTarget区别

  • 先诉重点理论:
  • target:触发事件的某个具体对象,只会出现在事件流的目标阶段(谁触发谁命中,所以肯定是目标阶段)
  • currentTarget:绑定事件的对象,恒等于this,可能出现在事件流的任意一个阶段中
  • 通常情况下terget和currentTarget是一致的,我们只要使用terget即可,但有一种情况必须区分这三者的关系,那就是在父子嵌套的关系中,父元素绑定了事件,单击了子元素(根据事件流,在不阻止事件流的前提下他会传递至父元素,导致父元素的事件处理函数执行),这时候currentTarget指向的是父元素,因为他是绑定事件的对象,而target指向了子元素,因为他是触发事件的那个具体对象
<div id="one">
   <div id="three"></div>
</div>
<script>
one.addEventListener('click',function(e){
    console.log(this);//one - 函数对应的区域
    console.log(e.target);  //three  - 多层套叠的时候,选中直接触发的区域
    console.log(e.currentTarget);  //one
},false);
</script>

捕获/阻止捕获、冒泡/阻止冒泡

原理

DOM事件流

这就要经过事件流,整个事件流分三个阶段:

  • 第一阶段是 捕获,事件从上(window)往下的过程;
  • 第二阶段是 目标阶段,如点击某个目标元素,事件通过捕获到达目标元素,就是目标阶段;
  • 第三个阶段是 冒泡,从目标元素再上传到window对象,就是冒泡的过程。

语法

document.getElementById("button").addEventListener("click",function(){
            alert("button");
        },true/false);
true:时间捕捉 外入内
false:事件冒泡 内到外 (默认)

事件冒泡例子(内到外)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>bubble</title>
    <style>
        button{
            background: red;
            color:white;
        }
        #third{
            width: 50px;
            height: 50px;
            border:thin solid red;
        }
        #second{
            width: 100px;
            height: 100px;
            border:thin solid red;
        }
        #first{
            width:200px;
            height: 200px;
            border:thin solid red;
        }
    </style>
</head>
<body>
    <div id="first">
        <div id="second" >
            <div id="third" >
                <button id="button">事件冒泡</button>
            </div>
        </div>
    </div>
    <script>

        document.getElementById("button").addEventListener("click",function(){
            alert("button");
        },false);

        document.getElementById("third").addEventListener("click",function(){
            alert("third");
        },false);

        document.getElementById("second").addEventListener("click",function(){
            alert("second");
        },false);        

        document.getElementById("first").addEventListener("click",function(){
            alert("first");
        },false);

    </script>
</body>
</html>

阻止事件冒泡

        document.getElementById("button").addEventListener("click",function(event){
            alert("button");
            event.stopPropagation();    
        },false);

事件捕获例子(外到内)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>bubble</title>
    <style>
        button{
            background: red;
            color:white;
        }
        #third{
            width: 50px;
            height: 50px;
            border:thin solid red;
        }
        #second{
            width: 100px;
            height: 100px;
            border:thin solid red;
        }
        #first{
            width:200px;
            height: 200px;
            border:thin solid red;
        }
    </style>
</head>
<body>
    <div id="first">
        <div id="second" >
            <div id="third" >
                <button id="button">事件冒泡</button>
            </div>
        </div>
    </div>
    <script>

        document.getElementById("button").addEventListener("click",function(){
            alert("button");
        },true);

        document.getElementById("third").addEventListener("click",function(){
            alert("third");
        },true);

        document.getElementById("second").addEventListener("click",function(){
            alert("second");
        },true);        

        document.getElementById("first").addEventListener("click",function(){
            alert("first");
        },true);

    </script>
</body>
</html>

stopPropagation()方法只能阻止事件的冒泡,而不能阻止事件捕获。

阻止事件捕获

document.getElementById("second").addEventListener("click",function(){
            alert("second");
            event.stopImmediatePropagation();
        },true); 

stopImmediatePropagation() 和 stopPropagation()的区别

  后者只会阻止冒泡或者是捕获。 但是前者除此之外还会阻止该元素的其他事件发生,但是后者就不会阻止其他事件的发生

js进行css操作

改变 HTML 样式

语法

document.getElementById(id).style.property = new style

1.直接设置style属性

 element.style.height = '100px';
document.getElementById("p2").style.color = "blue"; 

2.直接设置属性

element.setAttribute('height', '100px');

3.使用setAttribute设置style属性

element.setAttribute('style', 'height: 100px !important');

4.使用setProperty设置属性,通过第三个参数设置important

element.style.setProperty('height', '300px', 'important');

5.设置cssText

element.style.cssText = 'height: 100px !important';
element.style.cssText += 'height: 100px !important';

6. 改变class

比如JQ的更改class相关方法

因JS获取不到css的伪元素,所以可以通过改变伪元素父级的class来动态更改伪元素的样式

element.className = 'blue';
element.className += 'blue fb';

7. 创建引入新的css样式文件

function addNewStyle(newStyle) {
            var styleElement = document.getElementById('styles_js');

            if (!styleElement) {
                styleElement = document.createElement('style');
                styleElement.type = 'text/css';
                styleElement.id = 'styles_js';
                document.getElementsByTagName('head')[0].appendChild(styleElement);
            }

            styleElement.appendChild(document.createTextNode(newStyle));
        }

        addNewStyle('.box {height: 100px !important;}');

8. 使用addRule、insertRule

// 在原有样式操作
        document.styleSheets[0].addRule('.box', 'height: 100px');
        document.styleSheets[0].insertRule('.box {height: 100px}', 0);

        // 或者插入新样式时操作
        var styleEl = document.createElement('style'),
            styleSheet = styleEl.sheet;

        styleSheet.addRule('.box', 'height: 100px');
        styleSheet.insertRule('.box {height: 100px}', 0);

        document.head.appendChild(styleEl);        

js node操作

  • appenChild() - 接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点
  • removeChild() - 接受一个子节点作为参数,用于从当前节点移除该节点
  • replaceChild(new, old) - 将一个新的节点,替换当前节点的某一个子节点。它接受两个参数,第一个参数是用来替换的新节点,第二个参数将要被替换走的子节点
  • hasChildNodes() - 返回一个布尔值,表示当前节点是否有子节点
  • cloneNode() - 克隆一个节点。它接受一个布尔值作为参数,表示是否同时克隆子节点,默认是 false,即不克隆子节点
  • insertBefore(new, old) - 将某个节点插入当前节点的指定位置。它接受两个参数,第一个参数是所要插入的节点,第二个参数是当前节点的一个子节点,新的节点将插在这个节点的前面
  • contains() - 接受一个节点作为参数,返回一个布尔值,表示参数节点是否为当前节点的后代节点
  • isEqualNode() - 返回一个布尔值,用于检查两个节点是否相等。所谓相等的节点,指的是两个节点的类型相同、属性相同、子节点相同

html 元素

dataset属性,tabindex属性(遍历优先级),页面位置

document

document 节点是文档的根节点,有不同的办法可以获取,且都部署了 Document 接口:

  • 对于正常的网页,直接使用 document 或 window.document
  • 对于 iframe 载入的网页,使用 iframe 节点的 contentDocument 属性
  • 对 Ajax 操作返回的文档,使用 XMLHttpRequest 对象的 responseXML 属性
  • 对于某个节点包含的文档,使用该节点的 ownerDocument 属性

Document 属性

  • doctype - 包含了当前文档类型信息,对于 HTML5 文档,该节点就代表
  • documentElement - 表示当前文档的根节点,即 html
  • body - 返回当前文档的 body 节点
  • head - 返回当前文档的 head 节点
  • domain - 返回当前文档的域名
  • lastModified - 返回当前文档最后修改的时间戳,格式为字符串
  • location - 返回一个只读对象,提供了当前文档的 URL 信息,具体查看 MDN-location
  • title - 返回当前文档的标题
  • readyState - 表示页面的加载状态,可以在 readystatechange 中追踪页面的变化状态,可点击查看页面生命周期一节
  • cookie - 返回当前网页的 cookie,可点击查看 cookie 一节

以下属性返回文档内部特定元素的动态集合(HTMLCollection),可配合 namedItem 使用:

  • anchors - 返回网页中所有指定了 name 属性的 a 节点元素
  • forms - 返回页面中所有表单,即 form 标签
  • images - 返回页面所有图片元素,即 img 标签
  • links - 返回当前文档所有的链接元素,即具有 href 属性的元素,如 a 标签
  • scripts - 返回当前文档的所有脚本,即 script 标签
  • styleSheets - 返回一个类似数组的对象,包含了当前网页的所有样式表。该属性提供了样式表操作的接口

Document 方法

  • write() - open 方法新建一个文档;write 方法写入内容;close 方法关闭文档
  • querySelector() - 返回第一个匹配指定的 CSS 选择器的元素节点
  • querySelectorAll() - 返回所有匹配指定的 CSS 选择器的节点,返回的是 NodeList 类型的对象,静态集合
  • getElementById() - 返回匹配指定 ID 属性的元素节点
  • getElementsByClassName() - 返回一个类似数组的对象(HTMLCollection),包括了所有 class 名字符合指定条件的元素,动态集合
  • getElementsByTagName() - 返回一个类似数组的对象(HTMLCollection),包括了所有指定标签的元素,动态集合
  • getElementsByName() - 用于选择拥有 name 属性的 HTML 元素,返回的是 NodeList 类型的对象,静态集合

以下方法用于生成元素节点:

  • createElement() - 生成 HTML 元素节点
  • createTextNode() - 生成文本节点,参数为所要生成的文本节点的内容
  • createAttribute() - 生成一个新的属性对象节点
  • createEvent() - 生成一个事件对象,参数是事件类型,比如 UIEvents、MouseEvents、MutationEvents、HTMLEvents。IE 为 **createEventObject()**,不接受参数,返回通用 event 对象
  • adoptNode() - 将某个节点,从其原来所在的文档移除,插入当前文档,并返回插入后的新节点
  • importNode() - 用于创造一个外部节点的拷贝,然后插入当前文档。它的第一个参数是外部节点,第二个参数是一个布尔值,表示对外部节点是深拷贝还是浅拷贝,默认为 false 浅拷贝

Element

Element 对象对应网页的 HTML 标签元素,元素节点的 nodeType 属性都是 1。

Element 属性

  • id - 返回指定元素的 id 标识

  • attributes - 返回一个类似数组的对象 NamedNodeMap,成员是当前元素节点的所有属性节点,动态集合

  • tagName - 返回指定元素的大写的标签名,与 nodeName 属性的值相等

  • innerHTML - 返回该元素包含的 HTML 代码,该属性可读写,常用来设置某个节点的内容

  • outerHTML - 返回一个字符串,内容为指定元素的所有 HTML 代码,包括它自身和包含的所有子元素

  • style - 用来操作 CSS 样式,如 element.style.backgroundColor 等

  • className - 用来读取和设置当前元素的 class 属性。它的值是一个字符串,每个 class 之间用空格分割

  • classList

- 返回一个类似数组的对象 DOMTokenList,当前元素节点的每个 class 就是这个对象的一个成员

  • add() - 增加一个 class
  • remove() - 移除一个 class
  • contains() - 检查当前元素是否包含某个 class
  • toggle() - 将某个 class 移入或移出当前元素,可以接受第二个布尔值参数,true 则添加该属性
  • item() - 返回指定索引位置的 class
  • toString() - 将 class 的列表转为字符

获取 Element 节点相关的属性

  • children - 返回一个动态的 HTMLCollection 集合,由当前节点的所有 Element 子节点组成
  • childElementCount - 返回当前节点的所有 Element 子节点的数目
  • firstElementChild - 返回当前节点的第一个 Element 子节点,否则为 null;lastElementChild 返回最后一个子 Element 节点
  • nextElementSibling - 返回指定元素的后一个同级元素,否则为 null;previousElementSibling 为前一个同级元素

Element 位置信息

  • clientHeight - 返回元素节点的可见高度,包括 padding、但不包括水平滚动条、 border 和 margin 的高度;对应为 clientWidth
  • clientLeft - 返回元素节点左 border 的宽度,单位为像素,包括垂直滚动条的宽度,不包括左侧的 margin 和 padding;
  • clientTop - 返回网页元素顶部 border 的宽度,不包括顶部的 margin 和 padding
  • scrollHeight - 返回指定元素的总高度,包括由于溢出而无法展示在网页的不可见部分,包括 padding,但不包括 border 和 margin;对应为 scrollWidth
  • scrollLeft - 设置或返回水平滚动条向右侧滚动的像素数量。它的值等于元素的最左边与其可见的最左侧之间的距离
  • scrollTop - 设置或返回垂直滚动条向下滚动的像素数量。它的值等于元素的顶部与其可见的最高位置之间的距离

Element 方法

  • hasAttribute() - 返回一个布尔值,表示当前元素节点是否包含指定的 HTML 属性
  • getAttribute() - 返回当前元素节点的指定属性
  • removeAttribute() - 从当前元素节点移除属性
  • setAttribute() - 为当前元素节点新增属性,或编辑已存在的属性
  • querySelector() - 同 Document 方法,包括 querySelectorAll()、getElementBy…()
  • closest() - 返回当前元素节点的最接近的父元素(或者当前节点本身)
  • matches() - 返回一个布尔值,表示当前元素是否匹配给定的 CSS 选择器
  • remove() - 用于将当前元素节点从 DOM 树删除
  • scrollIntoView() - 滚动当前元素,进入浏览器的可见区域,可以接受一个布尔值作为参数。默认为 true,表示元素的顶部与当前区域的可见部分的顶部对齐(前提是当前区域可滚动);false 则为两者尾部对齐。

Text

Text 节点代表 Element 节点和 Attribute 节点的文本内容,可以使用 Document 节点的 createTextNode 方法创造一个 Text 节点。通过 firstChild、nextSibling 等获取 Text 节点。

Text 属性

  • data - 等同于 nodeValue 属性,用来设置或读取 Text 节点的内容
  • wholeText - 将当前 Text 节点与毗邻的 Text 节点,作为一个整体返回。大多数情况下,wholeText 属性的返回值,与 data 属性和 textContent 属性相同
  • length - 回当前 Text 节点的文本长度

Text 方法

  • appendData() - 在 Text 节点尾部追加字符串
  • deleteData() - 删除 Text 节点内部的子字符串,第一个参数为子字符串位置,第二个参数为子字符串长度
  • insertData() - 在 Text 节点插入字符串,第一个参数为插入位置,第二个参数为插入的子字符串
  • replaceData() - 用于替换文本,第一个参数为替换开始位置,第二个参数为需要被替换掉的长度,第三个参数为新加入的字符串
  • subStringData() - 用于获取子字符串,第一个参数为子字符串在 Text 节点中的开始位置,第二个参数为子字符串长度
  • remove - 移除当前 Text 节点

返回当前节点的内容,几种方法的比较

  • nodeValue - 一般只用在 Text 类型节点,其他大部分节点一律返回 null
  • textContent - 返回当前节点和它的所有后代节点的文本内容,会获取 display:none 的节点的文本,且不会理会 html 格式,直接输出不换行的文本
  • innerText - 返回当前节点和它的所有后代节点的文本内容,会忽略 display:none 的节点的文本
  • innerHTML - 返回该元素包含的 HTML 代码,该属性可读写,常用来设置某个节点的内容
Here is div-01
Here is div-02
var article = document.getElementsByTagName('article')[0]; article.innerText; // "Here is div-01 // Here is div-02" article.textContent; // " // Here is div-01 // Here is div-02 // Here is div-03 // " article.innerHTML; // " //
Here is div-01 //
Here is div-02 // //
//
// "

DOM实例

例子集合

查找集合

多个监听事件覆盖

当同一个对象使用.onclick的写法触发多个方法的时候,后一个方法会把前一个方法覆盖掉,也就是说,在对象的onclick事件发生时,只会执行最后绑定的方法。而用事件监听则不会有覆盖的现象,每个绑定的事件都会被执行。如下:

window.onload = function(){
 var btn = document.getElementById("yuanEvent");
 btn.onclick = function(){
  alert("第一个事件");
 }
 btn.onclick = function(){
  alert("第二个事件");
 }
 btn.onclick = function(){
  alert("第三个事件");
 }
}

最后只输出:第三个事件,因为后一个方法都把前一个方法覆盖掉了。
原生态的事件绑定函数addEventListener:

var eventOne = function(){
 alert("第一个监听事件");
}
function eventTwo(){
 alert("第二个监听事件");
}
window.onload = function(){
 var btn = document.getElementById("yuanEvent");
 //addEventListener:绑定函数
 btn.addEventListener("click",eventOne);
 btn.addEventListener("click",eventTwo);
}

输出:第一个监听事件 和 第二个监听事件

一次性事件绑定(执行中松绑)

// create a one-time event
function onetime(node, type, callback) {
    // create event
    node.addEventListener(type, function(e) {
        // remove event
        e.target.removeEventListener(e.type, arguments.callee);
        // call handler
        return callback(e);
    });
}
<body>
<input type="button" id="btn">
</body>
<script>
var btn=document.getElementById('btn');
function f(){
alert(123);
btn.removeEvenListener('click',f);
}
btn.addEventListener('click',f);
</script>

批量绑定事件 js

<body>  
<ul id="list">  
<li>1</li>  
<li>2</li>  
<li>3</li>  
<li>4</li>  
<li>5</li>  
</ul>  
<script>  
var list_obj = document.querySelectorAll('li');  
//var list_obj = document.getElementsByTagName('li'); 
for (let i = 0; i <= list_obj.length; i++) {        
  list_obj[i].onclick = function() {      
    alert(i);      
  }  
}  
</script>  
</body>  

易错点

var list_obj = document.getElementsByTagName('li');  
for (var i = 0; i <= list_obj.length; i++) {        
  list_obj[i].onclick = function() {      
    alert(i);      
  }  
}  

//当onclick事件发生的时候,会向上找到i对象的值。这个时候,由于已经循环完毕(编译),所以i的值是5
//所以注意闭包

解决办法

  1. let是块作用域,而var是函数或者全局作用域
  2. 利用闭包
list_obj[i].onclick = (function(x) {      
    alert(x);   
    //return function(){ alert(i);}
 })(i) 

控制网页前进和后退(历史页面)

这个前进后退按钮是需要在特定环境下才有效果的,即你需要从另一个页面进入到这个页面后,点击这个后退按钮才有后退的效果,否则是没有的。

<input type="button" value="后退" οnclick="javascript:history.go(-1);">

<input type="button" value="前进" οnclick="javascript:history.go(1);">

无刷新更改URL

data是你要存放的数据,可以使用history.state获取,title是标题,为空则不改变,url是新url

window.history.pushState(data:json,title:string,url:string); // 会存储在url历史中
window.history.replaceState(data:json,title:string,url:string); // 不会存储。。。

location

用来控制页面跳转

location.replace("xx"); //跳转
location.href = 'xxxx'; //同上
location.reload(); //刷新页面

定时器 - requestAnimationFrame

requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用

setInterval在执行完一次代码之后,经过了那个固定的时间间隔,它还会自动重复执行代码,而setTimeout只执行一次那段代码。(问题就是不精确)

requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果

var id = setInterval(callback/function,ms); //每隔ms毫秒执行一次函数(回调函数只写函数名)
var id = setTimeout(callback/function,ms); //在ms毫秒后执行一次函数
clearInterval(timer); //清理掉setInterval定时器
clearTimeout(timeout); //让setTimeout定时器失效

//对比:
//设置timer
window.requestAnimationFrame(callBack/function); //专门为动画设置的定时器(效果比setInterval流畅,每秒执行60次,大部分浏览器中,每秒执行次数和显示器刷新率一致)
var timer = requestAnimationFrame(function(){});

//取消
cancelAnimationFrame(1);//可以直接使用返回值取消
cancelAnimationFrame(timer);

实际例子

滚动动态加载内容

window.onscroll = function(e){    // 页面滚动事件(一般加给window)
    // 页面被卷起来的高度距离顶部或底部的距离
    var juan = document.documentElement.scrollTop;    // 获取页面被卷起来的高度,documentElement相当于html标签
    var total = document.documentElement.scrollHeight;    // 获取页面总高度
    var visul = window.innerHeight;    // 获取可见区的高度(即浏览器显示出来的高度)
    var bot = total - juan - visul;    // bot就是可见区下面的高度(这是我们需要的)
    ........    // 当bot小于某值时,加载新元素
}

详细讲解1

详细讲解2

右键点击事件

oncontextmenu

表单绑定事件的触发

  • onkeydown // 按下按键时立即触发,该事件一般绑定在document/window上,因为即使被绑定的表单没有获得焦点,该事件也会执行
  • onkeypress // 按下按键时立即触发,只有被绑定的元素获得焦点了,才会执行事件(适用于动态search)
  • onchange // 表单值改变时执行,按下按键时不是立即触发,而是等到输入完毕时才会触发(输入完毕指的是按下回车或表单失去焦点)
  • oninput // 表单值改变时立即触发

动画事件

  • animationend 该事件在 CSS 动画结束播放时触发
  • animationiteration 该事件在 CSS 动画重复播放时触发
  • animationstart 该事件在 CSS 动画开始播放时触发
  • transitionend 该事件在 CSS 完成过渡后触发

阻止默认事件

建立onclick事件方法,加入var ev=window.event; ev.preventDefault();

阻止a标签的默认事件:

<a href="javascript:void(0)">链接</a>

Reference:

https://www.cnblogs.com/xiaohuochai/p/5777757.html


Author: Savannah
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Savannah !
  TOC