【前端学习指南】JS-Web-API-DOM
-
JS基础知识
- 变量的类型和计算
- 原型和原型链
- 作用域和闭包
-
JS Web API
- DOM
- ajax
- BOM
- 存储
- 事件绑定
-
注意
- Vue和React框架应用广泛,封装了DOM操作,但DOM操作一直都是前端工程师的基础、必备知识。
- 只会vue而不懂DOM操作的前端程序员,不会长久,不要被框架限制住。
-
知识点
-
DOM 本质
- DOM的本质是一棵树(DOM树),从HTML文件解析出来的一棵树。
-
DOM 节点操作
-
获取DOM节点
const div1 = document.getElementById('div1') // 元素 console.log('div1', div1) const divList = document.getElementsByTagName('div') // 集合 console.log('divList.length:', divList.length) console.log('divList[1]:', divList[1]) const containerList = document.getElementsByClassName('container') // 集合 console.log('containerList.length:"', containerList.length) const pList = document.querySelectorAll('p') // 集合 console.log('pList:', pList)
-
DOM节点的attribute和property的异同
- property:修改对象属性,不会体现到HTML结构中
- attribute:修改HTML属性,会改变HTML结构
- 两者都会引起DOM重新渲染
- 尽量使用property
-
-
DOM 结构操作
-
新增/插入节点
const div1 = document.getElementById('div1') // 新建节点 const p1 = document.createElement('p') p1.innerHTML = 'this is new p1' // 插入节点 div1.appendChild(p1) // 移动已有节点,注意是移动! ! ! const p2 = document.getElementById('p2') div1.appendChild(p2) // 移动已有节点
-
获取子元素列表,获取父元素
// 获取子元素列表 const divChild=div1.childNodes console.log(divChild) // 获取父元素 console.log(p1.parentElement) console.log(p1.parentNode)
-
删除子元素
// 删除节点 div1.removeChild(divChild[0])
-
-
DOM 性能
-
DOM操作非常“昂贵”,要避免频繁的DOM操作,可以进行如下操作:
-
对DOM查询做缓存。
// 不缓存DOM查询结果 for (let i = 0; i < doqyument.getELementsByTagName('p').length; i++) { // 每次循环,都会计算length,频繁进行DOM查询 } // 缓存DOM查询结果 const pList = document.getELementsByTagName('p') const length = pList.length for (leti = 0; i < length; i++) { // 缓存length,只进行一次DOM查询 }
-
将频繁操作改为一次性操作。
const listNode = document.getELementById('list') // 创建一个文档片段,此时还没有插入到DOM树中 const frag = document.createDocumentFragment() // 执行插入 for (let x = 0; x < 10; x++) { const li = document.createElement("li") li.innerHTML = 'List item' + x frag.appendChild(li) } // 都完成之后,再插入到DOM树中 listNode.appendChild(frag)
-
-
-
-
事件委托
-
正确答案
function delegate (element, eventType, selector, fn) { element.addEventListener(eventType, e => { let el = e.target while (!el.matches(selector)) { if (element === el) { el = null break } el = el.parentNode } el && fn.call(el, e, el) }) return element }
-
错误答案
// 错误在于,如果用户点击的是 li 里面的 span,就没法触发 fn,这显然不对。 ul.addEventListener('click', function (e) { if (e.target.tagName.toLowerCase() === 'li') { fn() // 执行某个函数 } })
-
用 mouse 事件写一个可拖曳的 div
https://jsbin.com/munuzureya/edit?html,js,output
var dragging = false var position = null xxx.addEventListener('mousedown',function(e){ dragging = true position = [e.clientX, e.clientY] }) document.addEventListener('mousemove', function(e){ if(dragging === false){return} console.log('hi') const x = e.clientX const y = e.clientY const deltaX = x - position[0] const deltaY = y - position[1] const left = parseInt(xxx.style.left || 0) const top = parseInt(xxx.style.top || 0) xxx.style.left = left + deltaX + 'px' xxx.style.top = top + deltaY + 'px' position = [x, y] }) document.addEventListener('mouseup', function(e){ dragging = false })
-