操作DOM
HTML文档
<body> <span>呵呵呵</span> <div id="container"> <span>哈哈哈</span> <input type="text"> <input type="text"> <input type="text"> <button id="btn">点我</button> </div> <img id="image" src="" alt=""> <form action=""></form> <p id="test" class="test1 test2 test3 test4">class</p> </body>
选择DOM元素
querySelector和querySelectorAll可以使用css选择器选择元素
querySelector返回一个Element元素
querySelectorAll会返回一个NodeList对象,包含所有匹配的元素
let x = document.querySelector("#btn") === document.querySelector("#container>button") x // true let container = document.querySelector("#container") // 在指定元素上使用时只会返回后代中匹配的元素 let span = container.querySelector("span") span // <span>哈哈哈</span> let inputList = document.querySelectorAll("#container>input") inputList // NodeList(3) [input, input, input] let newList = document.querySelectorAll("span,input,button") newList // NodeList(6) [span, span, input, input, input, button#btn]
相比于老式的选择方法来说,NodeList是死的,而HTMLCollection是活的,其length会随着文档结构的变化而变化
let newSpanList = container.querySelectorAll("span") let oldSpanList = container.getElementsByTagName("span") newSpanList // NodeList [span] oldSpanList // HTMLCollection [span] container.append(document.createElement("span")) newSpanList // NodeList [span] oldSpanList // HTMLCollection(2) [span, span]
文档结构
span.parentNode // 父元素 span.children // 子元素的NodeList,不含非Element节点 span.firstElementChild // 第一个子元素 span.lastElementChild // 最后一个子元素 span.previousElementSibling // 左侧同辈元素,没有则为null span.nextElementSibling // 右侧同辈元素,没有则为null
对文档进行遍历,并对所有元素执行指定函数
function traverse(e, f){ f(e) for(let child of e.children){ // 迭代所有子元素 traverse(child, f) } } function traverse2(e, f){ f(e) let child = e.firstElementChild // 链表式迭代 while(child !== null){ traverse2(child, f) child = e.nextElementSibling } }
若想不忽略Text节点甚至Comment节点(注释),可使用下列方法
span.childNodes // 只读的NodeList对象,包含所有类型的子节点 span.firstChild // 当前节点的第一个子节点 span.lastChild // 当前节点的最后一个子节点 span.previousSibling // 前一个同辈节点 span.nextSibling // 后一个同辈节点 span.nodeType // 表示节点类型的数值,Document节点为9,Element节点为1,Text为3,Comment为8 span.nodeValue // Text或Comment节点的文本内容 span.nodeName // Element节点的HTML标签名(大写)
属性
span.getAttribute() // 查询 span.setAttribute() // 设置 span.hasAttribute() // 检测 span.removeAttribute() // 删除 let image = document.querySelector("img") let url = image.src image.id === "image" // true let form = document.querySelector("form") form.action = "http://www.test.com/submit" form.method = "POST" form // <form action="http://www.test.com/submit" method="POST"></form>
class属性
let p = document.querySelector("#test") // classList 表示类名的集合,有add() remove() contains() toggle()方法 let classname = p.classList // DOMTokenList(4) ['test1', 'test2', 'test3', 'test4'] classname.remove("test4") classname.add("test0") classname // DOMTokenList(4) ['test1', 'test2', 'test3', 'test0']
元素内容
innerHTML直接更改内容,效率很高,但加设计序列化、解析,所以效率不高
document.body.innerHTML = "<h1>test</h1>" // 直接更改内容,效率很高 document.body.innerHTML += "<p>test2</p>" // 但追加设计序列化、解析,所以效率不高
纯文本内容
若想获得纯文本内容,可使用textContent
let para = document.querySelector("p") let text = para.textContent // 'test2' para.textContent = "hello world"
创建、插入和删除节点
创建节点
let paragraph = document.createElement("P") // 创建一个空的p元素 let emphasis = document.createElement("em") // 创建一个空的em元素
在子节点中添加
append()和prepend()接收任意多参数,参数可以是Node节点可以是字符串,append添加到末尾,prepend添加到开头
emphasis.append("World") // 向em元素中添加文本 paragraph.append("hello", emphasis, "!") // 向p中添加文本和em元素 paragraph.prepend("begin ") // 在第一个子节点添加文本 paragraph.innerHTML // 'beginhello<em>World</em>!'
在同级节点添加
before()和after()也接收任意多参数,表示在当前节点前/后添加
para.after(paragraph)
paragraph.before(document.createElement("hr"))
复制
注意,同一个节点只能存在一个,如果将该节点插入到另一个位置,之前的就会消失,而不是复制
若想创建副本,可使用cloneNode(),传入true复制全部内容
paragraph.after(paragraph.cloneNode(true))
替换或移除
remove()可以将节点从文档中删除,或使用replaceWith()替换
para.replaceWith(paragraph) // 参数为新节点 paragraph.remove() // remove无需参数