JS DOM操作(2) 事件(1)

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>

我的實(shí)現(xiàn)

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>

我的實(shí)現(xiàn)

參考
關(guān)于DOM2級(jí)事件的事件捕獲和事件冒泡

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末睦优,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子壮不,更是在濱河造成了極大的恐慌汗盘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件询一,死亡現(xiàn)場(chǎng)離奇詭異衡未,居然都是意外死亡尸执,警方通過查閱死者的電腦和手機(jī)家凯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門缓醋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绊诲,你說我怎么就攤上這事送粱。” “怎么了掂之?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵抗俄,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我世舰,道長(zhǎng)动雹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任跟压,我火速辦了婚禮胰蝠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘震蒋。我一直安慰自己茸塞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布查剖。 她就那樣靜靜地躺著钾虐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪笋庄。 梳的紋絲不亂的頭發(fā)上效扫,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音直砂,去河邊找鬼菌仁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛哆键,可吹牛的內(nèi)容都是我干的掘托。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼籍嘹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼闪盔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起辱士,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤泪掀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后颂碘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體异赫,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了塔拳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鼠证。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖靠抑,靈堂內(nèi)的尸體忽然破棺而出量九,到底是詐尸還是另有隱情,我是刑警寧澤颂碧,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布荠列,位于F島的核電站,受9級(jí)特大地震影響载城,放射性物質(zhì)發(fā)生泄漏肌似。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一诉瓦、第九天 我趴在偏房一處隱蔽的房頂上張望川队。 院中可真熱鬧,春花似錦垦搬、人聲如沸呼寸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽对雪。三九已至,卻和暖如春米绕,著一層夾襖步出監(jiān)牢的瞬間瑟捣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來泰國打工栅干, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留迈套,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓碱鳞,卻偏偏與公主長(zhǎng)得像桑李,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子窿给,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 作者:codeXiu 來源:掘金 事件流 事件流一共由三個(gè)階段分別是: 1.捕獲階段 2.目標(biāo)階段 3.冒泡階段 ...
    強(qiáng)哥科技興閱讀 505評(píng)論 0 1
  • 聲明:本文來源于http://www.webzsky.com/?p=731我只是在這里作為自己的學(xué)習(xí)筆記整理一下(...
    angryyan閱讀 7,007評(píng)論 1 6
  • 事件:交互體驗(yàn)的核心贵白,div.onclick = function(){};// "="號(hào)左邊就是事件了,右邊是觸...
    官清歲月閱讀 343評(píng)論 0 1
  • 1. 事件冒泡與事件捕獲 事件冒泡和事件捕獲分別由微軟和網(wǎng)景公司提出崩泡,這兩個(gè)概念都是為了解決頁面中事件流(事件發(fā)生...
    cbw100閱讀 2,696評(píng)論 0 8
  • 以前總感覺三十而立很遠(yuǎn)禁荒,轉(zhuǎn)眼間已經(jīng)到了而立之年。到了而立之年時(shí)角撞,面臨的是更種的困惑呛伴,該拿出什么來立勃痴? 前些天在微博...
    MrGowiy閱讀 415評(píng)論 0 0