节点类型
一共有 12 个节点类型,每个节点都有nodeType
属性
下面是节点常量
Node.ELEMENT_NODE
(1)元素节点document.createElement("li")
Node.ATTRIBUTE_NODE
(2) 属性节点document.createAttribute("align")
Node.TEXT_NODE
(3) 文本节点document.createTextNode('text')
Node.CDATA_SECTION_NODE
(4) CDATA 区块 XML 中才有Node.ENTITY_REFERENCE_NODE
(5)Node.ENTITY_NODE
(6)Node.PROCESSING_INSTRUCTION_NODE
(7)Node.COMMENT_NODE
(8) 注释节点document.createComment('注释')
Node.DOCUMENT_NODE
(9) document 节点Node.DOCUMENT_TYPE_NODE
(10) doctype 节点 不支持动态创建Node.DOCUMENT_FRAGMENT_NODE
(11) 文档片段 fragment 节点document.createDocumentFragment()
Node.NOTATION_NODE
(12)
<div class="nodeDiv">
<p>第一元素节点</p>
<div class="childDiv">第四个子节点</div>
<!-- 注释节点 -->
</div>
<script>
const nodeDiv = document.querySelector(".nodeDiv")
const childDiv = document.querySelector(".childDiv")
console.log(nodeDiv.nodeType) //1
console.log(nodeDiv.nodeName) //DIV
console.log(nodeDiv.nodeValue) //null
console.log(nodeDiv.childNodes) // NodeList(5)[text,p,text,div,text,comment,text]
console.log(nodeDiv.firstChild) //#text
console.log(nodeDiv.lastChild) // #text
console.log(nodeDiv.hasChildNodes()) // true 是否有子节点
console.log(nodeDiv.ownerDocument) // #document 获取文档节点
console.log(nodeDiv.parentNode) //body
console.log(childDiv.previousSibling) // #text
console.log(childDiv.previousElementSibling) // p
console.log(childDiv.nextSibling) // #text
console.log(childDiv.nextElementSibling) // null
console.log(childDiv.parentNode) //div.nodeDiv
使用文档片段优化代码
<div class="app">
<ul></ul>
</div>
<script>
const phones = ["huawei", "xiaomi", "oppo"]
const ul = document.querySelector(".app ul")
const fragment = document.createDocumentFragment()
phones.forEach((item) => {
let li = document.createElement("li")
let text = document.createTextNode(`${item}`)
li.appendChild(text)
fragment.appendChild(li)
})
ul.appendChild(fragment)
</script>
javascript 动态创建样式
let css = `
body {
margin:0;
padding:0;
}
.app {
width: 80%;
margin: 0 auto;
color:red;
}`
function craeteStyles(css) {
const style = document.createElement("style")
style.type = "text/css"
style.appendChild(document.createTextNode(css))
const head = document.querySelector("head")
head.appendChild(style)
}
craeteStyles(css)
将字符串解析为dom
的方法
- 使用
innerHTML
document.body.innerHTML = '<div>使用innerHTML</div>'
- 使用
DOMParser
注意:DOMParser
将字符串解析为document
文档,并不是dom
let domString = `
<div class='userInfo'>
<p>username</p>
<p>password</p>
</div>
`
const parser = new DOMParser()
const doc = parser.parseFromString(domString, "text/html")
const div = doc.querySelector(".userInfo")
你不能直接插doc,因为它并不是一个dom,你需要选择这个document中的某个节点
console.log(doc) //#documnet
console.log(div)
document.body.appendChild(div)
MutationObserver 监听 dom 更新
dom 更新时异步执行回调
mutationRecords 记录到底是什么发生了变化
let observer = new MutationObserver((mutationRecords) => {
console.log("<body> attributes changed")
console.log(mutationRecords)
})
// 监听body上面的属性,属性更新就触发回调
observer.observe(document.body, { attributes: true })
document.body.className = "foo"
console.log("Changed body class")
获取节点
- 获取
html
节点
document.documentElement
- 获取
head
节点
document.head
- 获取
body
节点
document.body
- 获取指定元素节点
document.getElementById()
通过id
获取指定节点document.getElementsByClassName()
通过类名获取节点集合HTMLCollection
HTMLCollection
是一个类数组可以使用Array.from()
转真数组
或者使用call
来调用数组上的方法document.getElementsByTagName()
通过标签名获取节点集合document.getElementsByName()
通过name
获取元素集合document.querySelector()
通过css选择器来获取标签document.querySelectorAll()
创建节点
document.createElement()
创建标签节点document.createTextNode('text')
创建文本节点
挂载节点
element.append()
追加一组子节点
element.appendChild(ele)
element.insertBefore(element,target)
在某个节点前面插入节点
element.replaceChild(新的节点,旧的节点)
替换节点
克隆节点
element.cloneNode(true/false)
当为false只克隆目标节点,当为true克隆目标节点及其子孙节点
删除节点
element.removeChild()
删除某个子节点
element.remove()
删除当前节点,以及子孙节点
NodeList 与HTMLCollection
NodeList | HTMLCollection |
---|---|
静态集合/实时集合 | 实时集合 |
Node.childNodes返回动态集合,document.querySelectorAll 返回静态集合 | Node.children |
类数组 | 类数组 |
有forEach | 没有forEach |
实时集合指,dom更新集合实时更新
对于实时集合最好是使用Array.from()创建副本再进行操作
属性与样式
元素自定义属性
h5规定自定义属性需要以data-
开头
获取元素的自定义属性对象dataset
element.dataset
- 获取节点状态
Element.getAttribute(key)
- 为节点添加修改状态
Element.setAttribute(key,value)
- 移除状态
Element.removeAttribute(key)
样式
style对象只能获取行内样式
getComputedStyle(element)
获取节点样式
替换类名样式className
classList
element.classList.add()
添加样式
element.classList.remove()
移除样式
element.classList.target()
没有就添加,有就移除
element/classList.contains()
是否有这个样式
焦点管理
document.activeElement
,始终包含当前拥有焦点的DOM元
素。
document.hasFocus()
表示文档是否拥有焦点:
元素尺寸
元素偏移量
element.getBoundingClientRect().
获取元素的大小及相对视口的位置 小数offsetHeight
获取元素的高度height=content+padding+border
这是整数含滚动条offsetLeft
相对于相对定位的父容器的位置offsetTop
相对于相对定位的父容器的位置offsetWidth
获取元素的宽度width=content+padding+border
这是整数含滚动条
客户端尺寸
clientHeight
不包括border
和滚动条clientWidth
滚动尺寸
scrollHeight
scrollLeft
scrollTop
scrollWidth
API | 计算方式 |
---|---|
clientWidth /clientHeight | 元素内容+padding 不含border 和滚动条 |
clientTop /clientLeft | border-top-width /border-left-width |
offsetParent | 返回第一个有定位的父元素 |
offsetWidth /offsetHeight | 元素内容+padding +border +滚动条 |
offsetTop /offsetLeft | 当前元素到offsetParent 边框的距离 |
scrollWidth /scrollHeight | 元素内部的高宽(包括溢出部分) |
scrollTop /scrollLeft | 表示滚动条滚动的距离 |
getBoundingClientRect() | 返回元素的大小(不含border )以及相对视口的位置 |
检查滚动条是否滚动到底
scrollTop + clientHeight >= scrollHeight
Math.abs(element.scrollHeight - element.clientHeight - element.scrollTop) < 1
事件
事件捕获,事件冒泡,事件流
- 事件捕获:
windown
—>document
---->html
—>body
—>....
—>targetDIV
它是从面到点的传播,这样的目的是方便拦截事件 - 事件冒泡:
windown
<—document
<----html
<—body
<—....
<—targetDIV
它是从点到面的传播 - 事件流:事件捕获—>目标元素---->事件冒泡(事件流也是事件执行顺序)
下面案列中,由于按钮本身并没有注册事件处理程序,因此click
事件冒泡到document.body
,从而触发了在它上面注册的处理程序。
document.body.onclick = function(event) {
// currentTarget时绑定事件的元素
console.log(event.currentTarget === document.body); // true
console.log(this === document.body); // true
// event.target是点击目标
console.log(event.target === document.getElementById("myBtn")); // true
}
阻止表单默认行为
- 将
button
,input
的type
属性改为button
- 在事件监听器中(事件处理函数)中使用
event.preventDefault()
阻止事件传播
1.event.stopPropagation()
阻止事件冒泡和捕获传递,当前元素的其它事件可以触发
2. event.stopImmediatePropagation
阻止事件冒泡和捕获传递,当前元素的其它事件不可出触发
添加、移除事件程序
// 添加事件处理程序
btn.onclick=(event)=>{
}
// 移除事件
btn.onclick=null
// 添加事件监听器
btn.addEventListener('click',(event)=>{
})
// 移除事件监听器
inpt.removeEventListener('click',listener)
创建事件
创建自定义事件
-
event = document.createEvent(type);
-
event = new Event(typeArg, eventInit)
-
event = new CustomEvent(typeArg, customEventInit);
绑定事件
element.addEventListener(event,hander)
触发事件
dispatchEvent(event)