Bom知識不難,就是東西比較多,耐心理解此篇文章,會讓你收穫滿滿。相信自己,認真看完。`
BOM(全稱:BrowserObjectModel)瀏覽器模型
有很多小白同學一聽到Bom
這個詞,瞬間暈倒,根本不懂到底是什麼,看以上的全稱來翻譯,就是瀏覽器中的東西,我們前端瀏覽器的主要方式在開發中來講,核心就是window。很多同學還聽過一個詞叫Dom
,初學者來講,這兩個很容易讓人有“跳樓”的想法,其實學好了這兩個,js中也就明白了一半的知識。
先說說這兩個的區別,學過html
的同學都知道,html主要是使用標籤,標籤在頁面中其實就是以節點的方式存在的,比如各種嵌套,就是分了很多的標籤節點,然後才能開發出想要的佈局頁面。那麼Dom
其實就是在用js控制這些標籤節點,然後操作各種事情。比如用js創建一個a標籤,就可以說創建了一個節點;再或者,用js寫出a標籤的樣式,就可以說控制了節點的樣式。完全可以這樣理解,但心裡要明白,這個標籤是js創建出來的,js控制了Dom節點,而非html寫出來的,兩者是有本質上的區別。那麼Bom
是來操作瀏覽器窗口的,比如你alert出一個彈窗,就是在操作Bom,你打開一個新的窗口,也是在操作Bom。所以理解為Bom是操作瀏覽器window的,這樣兩者的區別就很顯然了。
--window對象和全局作用域--
bom的核心對象是window,它表示瀏覽器的一個實例。在瀏覽器中,window對象有雙重角色,即是javascript訪問瀏覽器窗口的一個接口,又是ECMAscript規定的Global(全局)對象。因此所有在全局作用域中聲明的變量、函數都會變成window對象的屬性和方法。如:
var name = 'xiaoming';
function lookName(){
alert(this.name);
}
console.log(window.name); //xiaoming
lookName(); //xiaoming
window.lookName(); //xiaoming
從上看出,我們在全局作用域下定義的name,被歸在了window對象下,所以可以通過window.name訪問,也可以用通過window.lookName()訪問函數lookName()。由於是全局作用域,所以this指向了window對象,那麼this.name自然也能訪問到。
delete操作符
️注意:全局定義的屬性不能用delete操作符刪除,在window對象上直接定義的屬性可以。
var name1 = 'xiaoming'; // 全局定義name1
window.name2 = 'xiaoli'; // 在window上定義name2
console.log(delete window.name1); // 由於全局定義的不能用delete刪除,所以會返回false
console.log(delete window.name2); // window上的可以被delete刪除,會返回true
--window窗口--
窗口位置:
在各個瀏覽器當中,IE、Safari、Opera、Chrome 都提供了位置屬性:screenLeft
和screenTop
。
分別表示:“瀏覽器窗口相對於屏幕左邊和上邊的位置”。
但是火狐 (firefox) 卻提供了不同的屬性:screenX
和screenY
來表示上述位置。
更有趣的是歐朋瀏覽器(Opera),四個屬性都提供,但screenX、screenY 和 screenLeft、screenTop
屬性卻不對應,所以不建議在Opera中使用。
我們可以用自己的電腦試著打印一下你的窗口位置(用Chrome)舉例:
var left = window.screenLeft;
var top = window.screenTop;
console.log(left);
console.log(top);
但是這個案例並不能跨瀏覽器兼容,因為剛才提到過,firefox不支持screenLeft
和screenTop
,所以我們要跨瀏覽器兼容,需要做個判斷:
var left = (typeof window.screenLeft == 'number') ? window.screenLeft : window.screenX
var top = (typeof window.screenTop == 'number') ? window.screenTop : window.screenY
這樣使用一個三目運算就可以兼容firefox來獲取瀏覽器窗口的位置。
窗口大小:
如果需要跨瀏覽器兼容,來確定一個窗口的大小也略有不同。
IE9+、firefox、Safari、Opera、Chrome都提供了4個屬性: innerHeight
、innerWidth
、outerHeight
、outerWidth
這四個屬性均可以返回瀏覽器窗口大小,不過略有不同:
IE9+、firefox、Safari中,outerHeight
和 outerWidth
返回瀏覽器窗口本身的尺寸。
Opera、Chrome中,innerHeight
和 innerWidth
表示窗口容器的大小;outerHeight
和 outerWidth
表示的是視圖區域的大小。
在IE、firefox、Safari、Opera、Chrome中,有兩個相同的方法均提供了頁面可視窗口的大小,分別為:
document.documentElement.clientHeight // 視圖區域的高度
document.documentElement.clientWidth // 視圖區域的寬度
上述圖片的視圖區域寬高,就是用此方法打印出來的。
不過,這兩個方法必須要在標準模式css1Compat
下才有效;混雜模式BackCompat
下需要通過下邊方法才能有效獲取寬高信息:
document.body.clientHeight // 視圖區域的高度
document.body.clientWidth // 視圖區域的寬度
兩種模式我們可以用console.log(document.compatMode == "CSS1Compat" ? "當前處於標準模式" : "當前處於混雜模式")
來判斷,現在目前幾乎都是標準模式了。(如果不清楚兩種模式的區別,推薦一篇簡書中的文章:https://www.jianshu.com/p/4aa37da38b81 ,看起來還不錯。)
所以,要跨模式獲取可視區域的窗口大小,需要進行判斷當前的模式:
// 判斷方法:document.compatMode
if(document.compatMode == 'css1Compat'){
var h = document.documentElement.clientHeight
var w = document.documentElement.clientWidth
}else{
var h = document.body.clientHeight
var w = document.body.clientWidth
}
console.log(h)
console.log(w)
// 這樣就獲取到了當前可視區域的大小
當然,移動端開發也有窗口的大小,如果你沉迷於技術上的鑽研,推薦一位移動開發諮詢師寫的文章:https://quirksmode.org/mobile/viewports2.html 全英文版,如果你的英語不好,可以使用瀏覽器編譯出中文,也能理解到大概的含義。
--導航和打開窗口--window.open()
window.open()
方法即可以導航到一個特定的URL,也可以打開一個新的瀏覽器窗口。
window.open()
可接收4個參數:1.url地址 2.窗口目標target 3.窗口設置的字符串 4.取代當前頁面的布爾值
,分別說一下:`
url地址:就是要加載的瀏覽器地址。
窗口目標:類似與a
標籤中的target屬性。如果當前有與target相同的窗口,則會在當前窗口加載url。當然,我們也可以傳遞特殊的名稱,例如經常見到的 _blank
,_top
,_self
,_parent
。
窗口設置的字符串:設置這個的前提是我們加載的url就跳轉到一個新的窗口,而不是在當前窗口加載,那麼這個參數就很有趣了。我們可以隨意設置新窗口的大小,和彈出的位置。如設置寬500,高500的正方形窗口,也可以設置窗口上邊座標與左邊的座標。但要記住,這個參數是以字符串的形式體現的。我們以博主的博客地址https://yq.aliyun.com/u/villin
舉例:
window.open('https://yq.aliyun.com/u/villin','_blank','width=500,height=500,top=100,left=100')
可以複製這個代碼到你的瀏覽器,會看到彈出一個博客窗口,並且窗口寬高為500,位於屏幕下移100像素,左移100像素。
同時我們還可以通過resizeTo()
和moveTo()
兩個方法再次操作新打開窗口的大小和位置,也可以通過close()
方法關閉窗口:
var winURL = window.open('https://yq.aliyun.com/u/villin','_blank','width=500,height=500,top=100,left=100');
// 再次調整大小
winURL.resizeTo(500,300); // resizeTo()接收兩個參數,一個是寬度,一個是高度,當窗口打開時,再次調整為寬500px,高300px。
// 再次移動位置
winURL.moveTo(200,200); // moveTo()接收兩個參數,一個是距屏幕top的距離,一個是距屏幕left的距離。
// 3s後關閉窗口
setTimeout(() => {
winURL.close()
},3000) // setTimeout方法:等待一定時間後才開始執行某個任務,兩個參數,第一個是方法,第二個是等待時間。
當然,這個參數不僅僅只有這四個屬性,還有location,menubar,resizable,scrollbars,toolbar
等等。都代表著窗口所顯示的菜單欄或其他狀態欄,不過目前用到的也比較少,因為每個瀏覽器兼容性並不一致。
取代當前頁面的布爾值:這個參數只有在不打開新的窗口下使用,使用當前頁面的瀏覽歷史記錄,然後打開新的瀏覽頁面。
--超時調用和間歇調用--setTimeout()/setInterval()
setTimeout()
超時調用:等待特定時間後,執行某個方法
。兩個參數,一個是要執行的代碼方法,一個是要等待執行的時間(毫秒mm):
setTimeout(function(){
alert('hello,world')
},2000) // 等待2秒後,彈出hello,world
setTimeout(()=>{
alert('hello,world')
},2000) // 也可以使用箭頭函數
setTimeout("alert('hello,world')") // 也可以直接寫成字符串方法,不過本方法不推薦使用。
```setInterval()```**間歇調用:**```每間隔一段時間後,都執行某個方法```。兩個參數,一個是要執行的代碼方法,一個是要等待執行的時間(毫秒mm):
間歇調用與超時調用的方法一樣,就是間歇調用是重複不斷的執行某個方法,所以可能會某個執行程序還沒執行完,就再次的調用了該方法,一般再我們開發中,不到不得已不建議用這個方法。要是用此方法,那麼要在頁面關閉前,一定要用```clearInterval()```清空這個方法,防止報錯:
console.log('hello,world')
},1000) // 每隔一秒就打印一次hello,world
clearInterval(id) // 在頁面執行後,記得清空這個方法
**--系統對話框--**
瀏覽器通過三種對話框方式向用戶展示消息:
```1.alert() 帶有一個確認按鈕的彈出框```
```2.confirm() 帶有一個確認按鈕和一個取消按鈕的彈出框```
```3.prompt() 帶有輸入框的對話彈出框,兩個參數:一個是提示信息,一個是輸入框默認文本```
alert()代碼:
alert('請輸入您的暱稱')
顯示如下:

confirm()代碼:
var con = confirm('您輸入的暱稱為:villin')
if(con){
console.log('用戶點擊了確定')
// 在此可以寫確定後的執行代碼
}else{
console.log('用戶點擊了取消')
// 在此可以寫取消後的執行代碼
}
// 這樣可以得到用戶輸入的返回值,記住,在chrome中,var後邊定義的變量不能為name,本人嘗試後得到的結果不準。
顯示如下:

prompt()代碼:
var con = prompt('您輸入名字','villin')
if(con){
console.log('用戶點擊了確定')
// 在此可以寫確定後的執行代碼
}else{
console.log('用戶點擊了取消')
// 在此可以寫取消後的執行代碼
}
顯示如下:

```這種對話框也很有趣,有興趣的,可以做一個反覆彈出的對話框,惡搞你的朋友,可以練習一下。```
**--location對象--**```重要``````重要``````重要```
```location```對象對於Bom來講,是最有用的對象之一,它提供了當前窗口中加載的文檔有關的信息,還提供了一些導航功能。
```location```對象即是window對象的屬性,又是document對象的屬性。可以說```window.location```和```document.location```引用的是同一個對象。
**location中提供了一些屬性:**
hash : 返回url中的hash(#號後邊的參數),如果url不包含散列,則返回空字符串。如:"#villin"
host : 返回服務器名稱和端口號(如果有端口號的話會返回)。如:“www.villin.com:8080”
hostname : 返回不帶端口號的服務器名稱。如:“www.villin.com”
href : 返回當前加載頁面的完整url。
pathname : 返回url的目錄文件名或文件路徑。
port : 返回url中指定的端口號。
protocol : 返回頁面使用的協議,“http”或“https”。
search : 返回url的查詢字符串,這個字符串以“?”開頭。
```舉例:(每次修改屬性後,頁面都會重新加載,hash除外)```
假設原地址:www.villin.com/name/
1.添加一個hash地址:
location.hash = "#aaa" 改變後: www.villin.com/home/#aaa
2.添加一個搜索條件:
location.search = "?q=html" 改變後: www.villin.com/home/?q=html
3.將服務器名稱修改為 www.abc.com ,後邊home路徑不變:
location.hostname = "www.abc.com" 改變後: www.abc.com/home/
4.修改原文件路徑為/name:
location.pathname = "name" 改變後:www.villin.com/name/
5.添加一個8080端口號:
location.port = 8080 改變後:www.villin.com:8080/name/
打開一個新的頁面的方法:
```window.location(www.baidu.com)```
```location.href(www.baidu.com)```
```location.assign(www.baidu.com)```
```location.replace(www.baidu.com)```
️這幾種方法都可以跳轉到新的頁面,目前常用的是```location.href()```方法。修改url後都會生成一條新的記錄,因此用戶可以通過瀏覽器單擊“後退”按鈕,返回到前一個頁面,若想禁用後退按鈕,使用```location.replace()```方法,即可禁用後退按鈕。
與其相關的方法還有一個```location.reload()```,此方法可以重新刷新當前頁面。不過值得注意的是,這個方法會根據最有效的方式刷新頁面,如果頁面自上一次請求以來沒有改變過,頁面就會從瀏覽器緩存中重新加載。如果要強制從服務器中重新加載,傳遞一個參數true即可。```location.reload(true) // 從服務器重新加載```
**--history對象--**
```保存著用戶瀏覽頁面的歷史記錄```
簡單介紹幾個常見方法:
```history.go(-1) // 後退一頁```
```history.go(1) // 前進一頁```
```history.go(2) // 前進兩頁```
```history.go(0) // 重新加載當前頁```
**--navigator對象--**
**--screen對象--**
由於window中以上兩個個對象並不常用,在這裡不做講解。若有需要,我們可以自己去查閱相關資料。```navigator```對象,我們可以自己在代碼中打印一下```console.log(window.navigator)```,自己可以擴展多瞭解一下瀏覽器的其他屬性。
weChat:VillinWeChat
歡迎提出寶貴意見