JavaScript中的dom操作
作为一个前端,各种dom操作是必须要会的,尽管现在很多插件已经帮助我们实现了很多功能,以及vue,react等框架也帮我们节省了很多的dom操作,但是随着我们水平进步到想要自己开发组件的时候就必须要会这些dom操作了,正应了那句话:哪有什么岁月安好,只是在有人替你负重前行
获取dom节点
| 方法 | 作用 |
|---|
| document.body | 获取body节点,返回body节点 |
| document.head | 获取head节点,返回head节点 |
| document.getElementById(id) | 通过id获取节点,返回获取的节点 |
| document.getElementsByClassName(className) | 通过class获取节点,返回由获取到的dom节点组成的伪数组 |
| document.getElementsByName(name) | 通过name获取节点,返回由获取到的dom节点组成的伪数组 |
| document.getElementsByTagName(tagName) | 通过标签名称获取节点,返回由获取到的dom节点组成的伪数组 |
| document.querySelector('选择器') | 通过选择器获取元素,返回页面中符合条件的第一个元素 |
| document.querySelectorAll('选择器') | 通过选择器获取元素,返回页面中符合条件的所有元素组成的伪数组 |
这一部分全部是选择元素的,不过里面隐藏了一道面试题,那就是请写出一个方法返回页面中出现最多次数的元素以及其出现的次数
function maxTagCount(){
const domList = document.querySelectorAll("*")
const len = domList.length
const target = {}
for(let i = 0; i < len; i++){
if(target[domList[i].nodeName]){
target[domList[i].nodeName] += 1
}else{
target[domList[i].nodeName] = 1
}
}
let max = 0;
let maxNode = 0
for(let k in target){
if(target[k] > max){
max = target[k]
maxNode = k
}
}
return `出现次数最多的元素为${maxNode}元素,出现次数为${max}`
}
节点类型
| nodeType | 节点类型 |
|---|
| 1 | 元素节点 |
| 2 | 属性节点 |
| 3 | 文本节点 |
创建节点
| 方法 | 作用 |
|---|
| document.createElement() | 创建元素节点 |
| document.createTextNode() | 创建文本节点 |
| document.createAttribute() | 创建属性节点 |
| document.createDocumentFragment() | 创建文档碎片节点 |
| document.createComment() | 创建一个注释节点 |
节点操作
| 方法 | 作用 |
|---|
| element.setAttributeNode(attrNode) | 设置属性节点 |
| element.setAttribute(attr, value) | 设置属性 |
| element.getAttribute(attr) | 获取属性 |
| element.append(element) | 追加子节点(支持批量插入) |
| element.appendChild(element) | 追加子节点 |
| element.remove() | 删除自身 |
| element.removeChild() | 删除子节点 |
| element.replaceChild(newNode, oldNode) | 替换节点 |
| element.insertBefore(newNode, oldNode) | 在已有元素前插入新节点 |
节点关系
| 属性 | 指向节点 |
|---|
| parentNode | 父节点 |
| parentElement | 父元素节点 |
| childNodes | 该节点第一层子节点组成的伪数组 |
| children | 该节点第一层子元素节点组成的伪数组 |
| childElementCount | 返回子元素节点的个数 |
| firstChild | 第一个子节点 |
| lastChild | 最后一个子节点 |
| firstElementChild | 第一个元素子节点 |
| lastElementChild | 最后一个元素子节点 |
| nextSibling | 下一个兄弟节点 |
| previousSibling | 上一个兄弟节点 |
| nextElementSibling | 后一个元素兄弟节点 |
| previousElementSibling | 前一个元素兄弟节点 |
dom的各种高度
| 属性 | 解释 |
|---|
| clientWidth | 可见区域的宽 |
| clientHeight | 可见区域的高 |
| offsetWidth | 可见区域的宽(包括边线的宽) |
| offsetHeight | 可见区域的高(包括边线的高) |
| scrollWidth | 元素正文全文的宽 |
| scrollHeight | 元素正文全文的高 |
| scrollTop | 元素滚动条滚上去的高度 |
| scrollLeft | 元素滚动条左边滚过去的宽度 |
| window.screen.width | 屏幕分辨率的宽 |
| window.screen.height | 屏幕分辨率的高 |
这些高度在开发中也是经常使用的,这里也是存在一个面试题的,如何实现一个无限下拉的列表
<style>
ul{
height: 100vh;
overflow-y: scroll;
}
</style>
<ul id="list"></ul>
const list = document.querySelector('#list')
let timer = null
function appendItems(count = 50){
for(let i = 0; i < count; i++){
const item = document.createElement('li')
item.innerText = `item${i}`
list.append(item)
}
}
appendItems()
list.addEventListener('scroll', (e)=>{
const pageHeight = e.target.scrollHeight
const scrollTop = e.target.scrollTop
const clientHeight = e.target.clientHeight
const bottom = pageHeight - scrollTop - clientHeight
if(bottom <= 100){
if(timer) clearTimeout(timer);
timer = setTimeout(()=>{
appendItems(50)
}, 500)
}
})
以上就是黑鸡对于dom操作做出的一些总结以及面试被问到的东西