前端 DOM、BOM(二)
BOM: Browser Object Model
什么是: 專門操作或訪問瀏覽器軟件的一批函數和對象何時: 只要想獲取瀏覽器軟件的信息,或操作瀏覽器窗口時如何: 包括:1個最大的對象: window
3個角色
1. 代替ECMAScript中的global充當全局作用域對象。
2. 包含了所有ECMAScript,DOM和BOM的函數和對象:
比如: window.Arraywindow.documentwindow.alert **3. 代表著當前正在打開的瀏覽器窗口** (1). 獲得窗口大小: 2組: a. 完整窗口大小: window.outerWidth .outerHeight小技巧: 如何判斷瀏覽器窗口被最小化:window.outerHeight<36px b. 僅文檔顯示區大小: window.innerWidth .innerHeight (2). 監控窗口大小變化: window.onresize=function(){ … } (3). 控制窗口滾動條的滾動: window.scrollTo(0, 垂直方向滾動到的位置)window.scrollBy(0, 垂直方向上滾動距離的變化量) (4). 監控窗口的滾動: window.onscroll=function(){//獲得當前頁面滾動過的距離var scrollTop=document.documentElement.scrollTop||document.body.scrollTop} (5). 打開和關閉窗口:window.open()window.close()打開和關閉窗口:
1. 打開新窗口: 4種需求:
1. 在當前窗口打開,可后退:html: <a href="url" target="_self">js: window.open("url", "_self") 2. 在當前窗口打開,禁止后退:js: location.replace("新url") 3. 在新窗口打開,可打開多個:html: <a href="url" target="_blank">js: window.open("url", "_blank") 4. 在新窗口打開,只能打開一個:html: <a href="url" target="自定義窗口名">js: window.open("url", "自定義窗口名")原理:
1. 每個窗口在內存中都有一個name屬性來唯一標識這個窗口 2. 瀏覽器規定: 相同name名的窗口,只能打開一個。后打開的同名窗口會覆蓋先打開的同名窗口。 3. 指定name屬性: 3種:(1). _self: 自動獲得當前窗口自己的name名,作為新窗口的name名。因為同名窗口只能打開一個,所以可實現在當前窗口打開。(2). _blank: 不指定窗口的name名,瀏覽器就會自動給每個窗口隨機分配窗口名。因為隨機分配的窗口名肯定不重復,所以可實現打開多個窗口的效果。(3). 自定義name名: 這個名稱的窗口,只能打開一個! 4. 如何指定name屬性: <a href="url" target="新窗口的name名"window.open("url", "新窗口的name名") 5. 沖突: 一定不要用"name" 當變量名,會和BOM中的window.name屬性沖突!三. history:
1. 什么是history: 當前窗口中保存成功訪問過的url的歷史記錄數組。 2. 何時: 只能用于前進和后退 3. 如何: history.go(1) 前進一步history.go(-1) 后退一步history.go(0) 刷新四. location:
1. 什么是location: 專門保存瀏覽器地址欄信息,并提供跳轉操作的函數 的對象
2. 何時: 獲取瀏覽器地址欄信息,或執行跳轉操作時
3. 獲得瀏覽器地址欄信息: location提供了一系列屬性,來分段獲得瀏覽器地址欄中url的各個部分信息
.href 完整url
.protocol 協議
.host 主機名+端口號
.hostname 僅主機名
.port 端口號
.pathname 相對路徑
.hash 錨點地址
.search 查詢字符串
4. 執行特殊的跳轉操作:
(1). 也可像window.open()一樣實現在當前窗口打開,可后退:
location.assign(“新url”)
location.href=“新url”
location=“新url”
(2). 可實現禁止后退: location.replace(“新url”)
(3). 刷新: 2種:
a. 普通刷新: 優先使用瀏覽器本地緩存中的資源文件來刷新。
包括: history.go(0) location.reload()
b. 強制刷新: 跳過瀏覽器緩存,總是從服務器端獲取新資源
何時: 當網頁中包含實時數據時: 股票價格,天氣預報,生產監控
如何: location.reload(true)
強迫
五. 事件:
1. 什么是事件: 瀏覽器自動觸發的,或用戶手動觸發的頁面元素內容或狀態的改變
2. 什么是事件處理函數: 當事件發生時希望自動執行的函數
3. 什么是事件綁定: 提前將事件處理函數賦值給元素的事件屬性。當事件發生時,瀏覽器會找到這個元素的事件屬性,自動執行提前保存在事件屬性上的事件處理函數。
4. 如何綁定事件: 3種:
(1). 在HTML中綁定:
(2). 在js中,一個事件只能綁定一個處理函數
a. 元素.onclick=function(){… …} b. 問題: 因為采用賦值方式,保存事件處理函數,所以,一個事件屬性上只能綁定一個處理函數。 如果希望一個事件上能綁定多個處理函數,又采用賦值方式,則后賦值的處理函數, 會覆蓋先賦值的處理函數。事件屬性上只能保存一個處理函數。 c. 原理:1). btnShoot.onclick=function(){…}也會添加事件監聽對象。每個事件監聽對象中包含三個值: 元素是誰,什么事件,處理函數是什么。也會將事件監聽對象添加到瀏覽器的事件監聽對象數組中2). 當事件發生時,瀏覽器使用遍歷的方式,用觸發事件的元素名和事件名作為查找條件,去事件監聽對象數組中查找符合條件的監聽對象,執行其處理函數。找到幾個匹配的,就執行幾個處理函數。3). 當第二次btnShoot.onclick=function(){ … }時,瀏覽器會先查找是否已經有了btnShoot元素上的click事件監聽對象。如果找到,就不再重復創建監聽對象。而僅僅用新函數覆蓋原監聽對象中的處理函數。結果,只有一個新的處理函數可以留下來。(3). 在js中,一個事件可以綁定多個處理函數:添加事件監聽對象的方式:
a. 事件監聽對象: 集中保存一個事件的元素、事件名和處理函數的一個對象。 b. 如何添加事件監聽對象: 元素.addEventListener("事件名", 處理函數)//添加事件 監聽 強調: 1).事件名,不要帶on前綴!2). 處理函數不要加(),因為處理函數不是立刻執行!只是暫時賦值給事件屬性,保存起來。只有當用戶觸發事件時,才調用事件處理函數。 c. 原理: 1). addEventListener()無論任何情況下都會添加事件監聽對象。所以,每調用一次addEventListener()就會創建一個新的事件監聽對象,保存當前元素,當前事件名以及當前新處理函數。然后,再將新的事件監聽對象加入瀏覽器的事件監聽對象數組中。2). 因為瀏覽器每次觸發事件時,都會完整遍歷事件監聽對象數組。如果數組中包含多個該元素的該事件的處理函數監聽對象,則會觸發多個處理函數。 d. 移除事件監聽: 1). 元素.removeEventListener("事件名",原處理函數)2). 問題: 移除事件監聽,必須使用原處理函數的引用才行。不能用匿名函數。因為function是創建一個新函數的意思。兩個匿名函數就算寫的完全一樣,可是也不是同一個函數對象。所以,如果添加事件監聽時,使用的是匿名函數,則移除事件監聽時,是不可能找到原處理函數對象的。3). 解決: 只要一個事件處理函數可能被移除,就不應該用匿名函數綁定。應該用有名稱的函數來綁定。這樣,在移除時,才能通過函數名變量中的地址,找到原處理函數。4). 強調: 一旦使用有名稱的函數添加事件監聽,會導致該監聽對象只能添加一次。因為瀏覽器規定,事件監聽數組中不能有完全相同的兩個監聽對象(元素相同,事件名相同,處理函數地址都是同一個函數地址!)5. 事件模型:
(1). 什么是事件模型: 事件模型是指從事件發生開始,到所有處理函數執行完,所經歷的過程 (2). 包括: 3個階段 a. 捕獲階段: 從頂級父元素<html>,到當前出發事件的元素,進行遍歷。記錄各級父元素上綁定的事件處理函數 b. 目標觸發: 優先觸發目標元素上的事件處理函數: 目標元素: 我們心里實際想點的那個元素。 c. 冒泡階段: 從當前目標元素向上,依次觸發捕獲階段記錄的各級父元素上的處理函數。6. 事件對象:
(1). 什么是事件對象: 當事件發生時自動創建的,保存所有事件信息的對象。 (2). 何時: 2個場景 a. 要獲得事件相關的信息時 b. 要改變事件的默認行為時 (3). 如何獲得事件對象: 不用自己創建!自動創建的! 當事件發生時,事件對象總是作為處理函數的第一個實參值自動傳入處理函數中,所以,我們只要在定義處理函數時,添加第一個形參,等著接就好了! //當事件發生時 event // ↓ 信任 btn.onclick=function(e){//e=event對象 }(4). 事件提供的屬性和方法:
a. 取消冒泡/停止漫延: e.stopPropagation()//停止 漫延 強調: e.stopPropagation()不會阻止自己的代碼執行。只會阻止自己的父元素上的處理函數執行。 b. 利用冒泡/事件委托/事件代理(delegate)1). 優化: 盡量減少事件監聽對象的個數。因為瀏覽器查找事件監聽對象是采用遍歷方式。如果監聽對象很多,會導致遍歷速度慢,進一步會導致事件響應慢。2). 何時用事件委托: 如果多個平級子元素需要綁定相同的事件時,都必須用事件委托來優化。3). 如何: 3步: i. 將事件只綁定在父元素上一份即可,所有子元素通過冒泡共用父元素上的一個處理函數問題: 因為事件是綁定在父元素上的。所以執行也是在父元素上執行。所以,父元素上事件處理函數中的this,早就不指子元素了。而是統一指父元素。但是我們又希望獲得實際點擊的那個目標元素,執行不同的操作。ii. 解決: 用e.target代替thise.target是當事件發生時牢牢記住目標元素的事件屬性,且不會隨冒泡而改變。問題: e.target不總是想要的元素。比如: 點在父元素上,或點在哪些裝飾性的子元素上,也會觸發事件,導致錯誤。iii. 解決: 在開始編寫正式邏輯之前,必須先驗證e.target是否想要的!只要e.target是想要的,才能繼續執行正常的邏輯。否則,就什么也不干! c. 阻止默認行為: (1). HTML中有些元素帶有默認行為:i. <a href="#xxx">點擊后會擅自修改地址欄,在url結尾加#xxx。ii. <input type="submit">點擊后會自動以form方式提交表單。(2). e.preventDefault()//阻止 默認 d. 鼠標位置: 3組:(1). 相對于屏幕左上角的距離e.screenX e.screenY(2). 相對于文檔顯示區左上角的距離e.clientX e.clientY(3). 相對于當前事件所在的元素左上角的距離e.offsetX e.offsetYDOM 增刪改查:
1. 查找:
(1). 不需要查找就可直接獲得的元素document.documentElement —— <html>document.headdocument.bodydocument.forms[i] (2). 按節點間關系查找:元素.parentNode元素.children元素.firstElementChild元素.lastElementChild元素.previousElementSibling元素.nextElementSibling (3). 按HTML查找: var 元素=document.getElementById("id")var 類數組對象=父元素.getElementsByTagName("標簽名")var 類數組對象=父元素.getElementsByClassName("class名")var 類數組對象=document.getElementsByName("name名") (4). 按選擇器查找:var 元素=父元素.querySelector("選擇器")var 類數組對象=父元素.querySelectorAll("選擇器")2. 修改:
(1). 內容: 元素.innerHTML 元素.textContent 元素.value (2). 屬性: a. 字符串類型的HTML標準屬性:1). 核心DOM: 元素.getAttribute("屬性名")元素.setAttribute("屬性名","值")2). HTML DOM: 元素.屬性名特例: class -> classNameHTML5: 元素.classList.add()元素.classList.remove() b. bool類型的HTML標準屬性:1). 不能用核心DOM2) 只能用元素.屬性名 c. 自定義擴展屬性:1). 只能用核心DOM2). 不能用.修改3). HTML5: <元素 data-自定義屬性="值">元素.dataset.自定義屬性 (3).樣式: 1). 修改樣式: 元素.style.css屬性名="值"元素.style.cssText="屬性名:值; 屬性名: 值; …"2). 獲取樣式: var style=getComputedStyle(元素)style.css屬性3. 添加元素:
(1). 添加一個元素: 3步: var a=document.createElement("a") a.href="http://tmooc.cn" a.innerHTML="go to tmooc" 父元素.appendChild(a); 或 父元素.insertBefore(a, 現有元素) 或 父元素.replaceChild(a, 現有元素) (2). 同時添加多個元素: 借助文檔片段 var frag=document.createDocumentFragment(); frag.appendChild(子元素) 父元素.appendChild(frag)4. 刪除: 父元素.removeChild(子元素)
5. HTML DOM:
(1). var img=new Image(); (2). select 和 option: a. select: .selectedIndex .options .length b. option: var opt=new Option(內容, 值) (3). table: a. table管著行分組: 1). 添加: var 行分組=table.createTHead() .createTBody() .createTFoot()2). 刪除: table.deleteTHead() .deleteTFoot()3). 獲取: table.tHead table.tFoot table.tBodies[i] b. 行分組管著行: 1). 添加: var tr=行分組.insertRow(i)2). 刪除: table.deleteRow(tr.rowIndex)3). 獲取: 行分組.rows[i] c. 行管著格: 1). 添加: var td=tr.insertCell()2). 刪除: tr.deleteCell(i)3). 獲取: tr.cells[i] (4). form 和 表單元素:1). form屬性: .elements .length2). 表單元素: a. 獲取: form.elements[i/id/name]如果有name屬性可簡寫為: form.nameb. 方法: 表單元素.focus()DOM優化: 4處
1. 查找:(1). 如果只用一個條件就可找到想要的元素,首選按HTML查找返回動態集合——首次查找,效率高!(2). 如果查找條件復雜,就用選擇器查找易用 2. 修改樣式: 盡量減少修改樣式的次數——減少重排重繪(1). 如果批量應用多個css屬性,首選用class修改(2). 如果必須用style修改,也可用元素.style.cssText一句話代替多句話修改樣式。 3. 添加元素: 盡量減少操作DOM樹的次數——減少重排重繪(1). 如果同時添加父元素和子元素,則先在內存中將子元素添加到父元素。最后再一次性將父元素添加到DOM樹(2). 如果同時添加多個平級子元素,則先在內存中將子元素添加到文檔片段中。最后再一次性將文檔片段添加到DOM樹總結
以上是生活随笔為你收集整理的前端 DOM、BOM(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学生每日计划表_初三学生逆袭每日计划表
- 下一篇: 柳传志的512天