1喊废、寫一個(gè)函數(shù),批量操作 css
function css(node, styleObject){
for(var key in styleObject){
node.style[key] = sytleObject[key]
}
}
css(document.body, {
'color': 'red',
'background-color': '#ccc'
})
2栗弟、如何獲取 DOM 計(jì)算后的樣式
//css
div {
color: red;
fontsize: 20px;
}
//html
<div id="name">海山城</div>
設(shè)置div的background為pink
document.querySelector("#name").style.background = 'pink'
檢查代碼發(fā)現(xiàn)相當(dāng)于做了這樣一件事污筷,相當(dāng)于添加了行內(nèi)樣式
<div id="name" style="background: pink;">海山城</div>
因此如果行內(nèi)樣式?jīng)]有某個(gè)屬性,通過這個(gè)方式是獲取不到該屬性對(duì)應(yīng)的值的
//css
div {
color: red;
fontsize: 20px;
}
//html
<div id="name" style="background:blue">海山城</div>
//JS
var background = document.querySelector("#name").style.background
var fontsize = document.querySelector("#name").style.fontsize
console.log(background) //"blue"
console.log(fontsize) //""乍赫,獲取不到
那么我就想獲取到某個(gè)元素的非行內(nèi)樣式怎么辦呢瓣蛀?
getcomputedStyle:獲取元素計(jì)算后的樣式饿凛,不要通過 node.style.屬性 獲取
//css
div {
color: red;
fontsize: 20px;
}
//html
<div id="name">海山城</div>
//JS
var color = window.getComputedStyle(document.querySelector("#name")).color
var fontsize= window.getComputedStyle(document.querySelector("#name"))['font-size']
//或者var fontsize= window.getComputedStyle(document.querySelector("#name")).fontSize
console.log(color)
console.log(fontsize)
注: window.getComputedStyle()得到的是一個(gè)存放了所有計(jì)算后的樣式的對(duì)象讼育,因此 . 和 [] 都可以訪問其中所有的屬性樣式,[]中用的是css寫法(font-size),想用 . 可以使用駝峰(fontSize)
3码耐、實(shí)現(xiàn)此效果
通過node.style.屬性添加樣式太麻煩仑撞,需要一條一條的添加伏钠∪絮耍可以將所有需要添加的屬性寫到一個(gè)class中,那個(gè)元素需要這些樣式纫塌,直接給這個(gè)元素添加這個(gè)class就行了
代碼實(shí)現(xiàn)
4诊县、onlick與addEventListener的區(qū)別?
用法:
//onclick
btn.onclick = function(){
console.log("第一")
}
// "第一"
//addEventListener
var btnClick = document.getElementById('btnClick');
btnClick.addEventListener('click', function() {
console.log("第一")
}, false)
btnClick.addEventListener('click', function() {
console.log("第二")
}, false)
/* "第一"
"第二" */
區(qū)別:
- 名稱的區(qū)別措左。一個(gè)是onclick依痊,而addEventListener中的參數(shù)是click
- onclick只可以綁定一個(gè)事件,而addEventListener可以綁定多個(gè)事件
btn.onclick = function(){console.log("第一")}相當(dāng)于對(duì)一個(gè)對(duì)象賦值怎披,那么在btn.onclick = function(){console.log("第二")}就會(huì)把前面的值覆蓋胸嘁,所以onclick不能綁定多個(gè)事件 - onclick只能是在默認(rèn)的冒泡階段,而addEventListener可以指定參數(shù)來設(shè)置是捕獲階段還是冒泡階段凉逛,第三個(gè)參數(shù)可以不寫(即為false)性宏,代表的是默認(rèn)的冒泡階段,如果是true則代表的是捕獲階段
5状飞、解釋DOM2事件傳播機(jī)制毫胜?
首先了解下什么是事件流?
事件流描述的是從頁面中接收事件的順序诬辈,比如有兩個(gè)嵌套的div酵使,點(diǎn)擊了內(nèi)層的div,這時(shí)候是內(nèi)層的div先觸發(fā)click事件還是外層先觸發(fā)焙糟?目前主要有三種模型
-
IE的事件冒泡:事件開始時(shí)由最具體的元素接收口渔,然后逐級(jí)向上傳播到較為不具體的元素
-
Netscape的事件捕獲:不太具體的節(jié)點(diǎn)更早接收事件,而最具體的元素最后接收事件酬荞,和事件冒泡相反
- DOM2級(jí)事件流:包括三個(gè)階段搓劫,事件捕獲階段,處于目標(biāo)階段混巧,事件冒泡階段,首先發(fā)生的是事件捕獲勤揩,為截取事件提供機(jī)會(huì)咧党,然后是實(shí)際目標(biāo)接收事件,最后是冒泡階段
再來看個(gè)DOM2事件傳播機(jī)制的有趣事例
事例代碼地址
代碼中嵌套了3個(gè)div陨亡,并且為每個(gè)div都綁定了對(duì)應(yīng)的捕獲以及冒泡事件傍衡。當(dāng)我點(diǎn)擊div#inner時(shí)深员,控制臺(tái)的結(jié)果為:
outer捕獲
middle捕獲
inner冒泡
inner捕獲
middle冒泡
outer冒泡
what?為啥inner冒泡會(huì)在inner捕獲前面M芄 >氤?
原理:DOM事件觸發(fā)分為三個(gè)階段
①绣的、事件捕獲階段叠赐,即由最頂層元素(一般是從window元素開始,有的瀏覽器是從document開始)開始屡江,逐次進(jìn)入dom內(nèi)部芭概,最后到達(dá)目標(biāo)元素,依次執(zhí)行綁定在其上的事件(不包括目標(biāo)元素上的事件)
②惩嘉、處于目標(biāo)階段罢洲,檢測(cè)機(jī)制到達(dá)目標(biāo)元素,按事件注冊(cè)順序執(zhí)行綁定在目標(biāo)元素上的事件文黎。
③惹苗、事件冒泡階段,從目標(biāo)元素出發(fā)耸峭,向外層元素冒泡桩蓉,最后到達(dá)頂層(window或document),依次執(zhí)行綁定再其上的事件(不包括目標(biāo)元素上的事件)抓艳。
所以触机,div#inner上的事件是處于目標(biāo)階段的事件,會(huì)按事件注冊(cè)順序執(zhí)行玷或,和設(shè)定的是捕獲還是冒泡事件并無關(guān)系
☆6儡首、有如下代碼,要求當(dāng)點(diǎn)擊每一個(gè)元素li時(shí)控制臺(tái)展示該元素的文本內(nèi)容偏友。不考慮兼容
<ul class="ct">
<li>這里是</li>
<li>海山城</li>
<li>大世界</li>
</ul>
<script>
//todo ...
</script>
方法一:利用this蔬胯。this指代的就是綁定事件的那個(gè)元素
var liList = document.getElementsByTagName('li')
for(var i=0; i<liList.length; i++){
liList[i].onclick = function(){
console.log(this.innerText)
}
}
方法二:利用閉包。
var liList = document.getElementsByTagName('li')
for(var i=0; i<liList.length; i++){
(function(new_i){
liList[new_i].onclick = function(){
console.log(liList[new_i].innerText)
}
})(i)
}
那么位他,問題來了氛濒,我不加立即執(zhí)行函數(shù)生成閉包不行嗎,就像下面這樣
var liList = document.getElementsByTagName('li')
for(var i=0; i<liList.length; i++){
liList[i].onclick = function(){
console.log(liList[i].innerText)//如果console.log(i)鹅髓,點(diǎn)擊任何li都會(huì)輸出3
}
}
點(diǎn)擊每個(gè)li會(huì)發(fā)現(xiàn)控制臺(tái)報(bào)錯(cuò)舞竿,什么原因呢?
原理:
- onclick的回調(diào)函數(shù)會(huì)被加入到任務(wù)隊(duì)列中窿冯,等主線程所有代碼執(zhí)行完畢骗奖,才開始執(zhí)行。因此,循環(huán)會(huì)先被執(zhí)行完执桌,最后得到i的值為length(我這里只有3個(gè)li鄙皇,i也就是3),最后無論點(diǎn)擊哪個(gè)li時(shí)仰挣,對(duì)應(yīng)的回調(diào)函數(shù)執(zhí)行console.log(liList[3].innerText)伴逸,已經(jīng)越界了,所以會(huì)報(bào)錯(cuò)!!!
- 如果給代碼塊包裝一個(gè)立即執(zhí)行函數(shù)膘壶,并把i作為參數(shù)傳入的話
相當(dāng)于var new_i = i错蝴,console.log(liList[new_i ].innerText。那么后續(xù)i++對(duì)當(dāng)前new_i并沒有影響
方法三:事件代理(推薦O阕怠J),不對(duì)每個(gè)節(jié)點(diǎn)都設(shè)置事件畜伐,對(duì)其父節(jié)點(diǎn)設(shè)置事件
var ul = document.querySelector('.ct')
ul.addEventListener('click',function(e){
console.log(e.target.innerText)
})
- 在事件處理程序內(nèi)部馍惹,this始終等同于currentTarget(綁定事件的目標(biāo)),而target是事件的實(shí)際目標(biāo)(實(shí)際點(diǎn)擊的目標(biāo))
- e是指event事件對(duì)象玛界,包含了創(chuàng)建它的特定事件有關(guān)的屬性和方法万矾,preventDefault(),stopPropagation()慎框,target這三個(gè)最為重要
- e是哪邊來的呢良狈?在addEventListener的內(nèi)部var event = {},然后系統(tǒng)收集到的方法屬性會(huì)被添加到對(duì)象中笨枯,最后callback(event)執(zhí)行薪丁,也就是把event作為參數(shù)傳入到了callback中,所以上述代碼等價(jià)于:
var ul = document.querySelector('.ct')
ul.addEventListener('click',function(){
console.log(arguments[0].target.innerText)//addEventListener函數(shù)的內(nèi)部會(huì)將event對(duì)象作為第一個(gè)參數(shù)傳入call函數(shù)中
})
7馅精、補(bǔ)全代碼
要求:
- 當(dāng)點(diǎn)擊按鈕開頭添加時(shí)在<li>這里是</li>元素前添加一個(gè)新元素严嗜,內(nèi)容為用戶輸入的非空字符串;當(dāng)點(diǎn)擊結(jié)尾添加時(shí)在最后一個(gè) li 元素后添加用戶輸入的非空字符串.
- 當(dāng)點(diǎn)擊每一個(gè)元素li時(shí)控制臺(tái)展示該元素的文本內(nèi)容洲敢。
<ul class="ct">
<li>這里是</li>
<li>饑人谷</li>
<li>任務(wù)班</li>
</ul>
<input class="ipt-add-content" placeholder="添加內(nèi)容"/>
<button id="btn-add-start">開頭添加</button>
<button id="btn-add-end">結(jié)尾添加</button>
<script>
//你的代碼
</script>
8漫玄、補(bǔ)全代碼
要求:當(dāng)鼠標(biāo)放置在li元素上,會(huì)在img-preview里展示當(dāng)前l(fā)i元素的data-img對(duì)應(yīng)的圖片压彭。
<ul class="ct">
<li data-img="1.png">鼠標(biāo)放置查看圖片1</li>
<li data-img="2.png">鼠標(biāo)放置查看圖片2</li>
<li data-img="3.png">鼠標(biāo)放置查看圖片3</li>
</ul>
<div class="img-preview"></div>
<script>
//你的代碼
</script>