原文參考http://mp.weixin.qq.com/s?__biz=MzU3MDA0NTMzMA==&mid=2247485490&idx=1&sn=15197b4b53e0669e4a017e54a31fb39c&source=41#wechat_redirect 使用原生js ...
原文參考http://mp.weixin.qq.com/s?__biz=MzU3MDA0NTMzMA==&mid=2247485490&idx=1&sn=15197b4b53e0669e4a017e54a31fb39c&source=41#wechat_redirect
使用原生js為了提高效率,純js操作dom
一 查詢DOM
document.querySelector()參數是任意css選擇器格式,只會返回第一個匹配到值
document.querySelectorAll()同上,返回結果不同,會返回所有查找到的值
儘量在父元素中查找指定dom,減少document的整個文檔查找,這樣可以簡化選擇器並提高性能。
與getElementsByTagName()這些方法的比較,querySelector()的結果不是動態的,當我們動態添加元素時,集合不會更新
代碼:
const elements1 = document.querySelectorAll('div')
const elements2 = document.getElementsByTagName('div')
const newElement = document.createElement('div')
document.body.appendChild(newElement)
elements1.length === elements2.length // 0 1 結果false
querySelectorAll()返回的結果不用調用node方法,結果也不是一個數組(是偽數組),需要轉為數組才能使用數組的方法
const myElements=document.querySelectorAll('.cla')
Array.from(myElements).forEach(doSomeThing)
Array.prototype.forEach.call(myElements,doSomeThing)
[].forEach.call(myElements,doSomeThing)
每個元素都有一些引用‘家族’的不需要說明的只讀屬性(即element屬性),並且是動態的,基於元素的
myElements.children子節點
myElements.firstElementChild第一個子節點
myElements.lastElementChild最後一個子節點
myElements.previousElementSibling前一個子節點
myElements.nextElementSibling後一個子節點
node屬性,除了parentElement可以是任何類型節點
myElements.childNodes
myElements.firstChild
myElements.lastChild
myElements.previousSibling
myElements.nextSibling
myElements.parentNode
myElements.parentElement
通過nodeType來判斷節點的類型
檢查節點的原型鏈可以使用instanceof
二 修改類和屬性
修改類
myElement.classList.add()
myElement.classList.remove()
myElement.classList.toggle()
訪問屬性
myElement.value
myElement.value = 'test'// 賦值
設置多屬性
Object.assign(myElement,{
value:'test',
id:'app'
})
以下方法會導致瀏覽器重繪消耗性能
getAttribute()
setAttribute()
removeAttribute()
三添加css樣式
使用駝峰形式
myElement.style.marginLeft = '1px'// 只會獲取明確屬性
window.getComputedStyle(myElement)// 可以獲取次元素所有css屬性集合,包括繼承下來的
window.getComputedStyle(myElement).getPropertyValue('width')// 獲取全部集合中的一種(如寬度)
四修改DOM
element1.appendChild(element2)
element1.insertBefore(element2,element3)// 在容器element1中,將element2插入到element3之前
五克隆一個元素
let myEleClone = myElement.cloneNode()// 參數為true將創建一個深層副本,它的子元素也會被克隆
六創建
創建元素
document.createElement('div')
創建文本節點
document.createTextNode('hell')
七刪除
parentBox.removeChild(myElement)// 從父容器中刪除子元素
myElement.parentNode.removeChild(myElement)
八讀寫元素屬性
innerHTML='<p>test</p>'// 元素中添加html內容
textContent='test'// 只能添加純文本
九事件監聽
使用addEventListener方法可以不斷綁定事件,事件都會觸發
myElement.addEventListener('click',function(event){
console.log(event.target);
})
event.target是觸發事件的元素
阻止預設事件e.preventDefault()
阻止事件冒泡e.stopPropagation()
myElement.addEventListener('click',function(){},true)
第一個參數是事件類型,第二個參數是回調函數,第三個參數是布爾值,true表示事件在捕獲階段執行false事件在冒泡階段執行。預設是false
removeEventListener()刪除事件監聽器
myElement.addEventListener('click',function(e){})// 第一個參數是事件類型,第二個參數是回調函數
事件委托
列表的每個列表需要添加綁定事件,可以使用這種方式,在父元素上綁定事件,利用冒泡原理在判斷觸發事件的元素,節約性能
parentBox.addEventListener('click',function(e){
console.log(e.target);
})
十 動畫
使用window.requestAnimationFrame()來同步更新,將更改安排到瀏覽器下次重繪中。
格式
const start = window.performance.now()
const duration = 2000
window.requestAnimationFrame(function fadeIn(now){
consot progress = now - start
myElement.style.opacity = progress / duration
if(progress < duration){
window.requestAnimationFrame(fadeIn)// 遞歸
}
})
十一 封裝自己方法
const $ = function $(selector, context = document) {
const elements = Array.from(context.querySelectorAll(selector))
return {
elements,
html(newHtml){
this.elements.forEach(element => {
element.innerHTML = newHtml
})
},
css (newCss) {
this.elements.forEach(element => {
Object.assign(element.style, newCss)
})
return this
},
on (event, handler, options){
this.elements.forEach(element => {
element.addEventListener(event, handler, options)
})
return this
}
}
}