前端學習之BOM與DOM操作彙總

前端學習之BOM與DOM

總結匯總一些常用的操作瀏覽器功能和頁面元素的API,如DOM文檔對象模型(Document Object Model)及BOM瀏覽器對象模型(Browser Object Model)等相關標準化的WebApi。

1. DOM樹操作

1.1 獲取元素
  • 根據ID獲取
<body>
    <div id="time">2019-9-9</div>
    <script>
        // 因爲我們文檔頁面從上往下加載,所以先得有標籤 所以我們script寫到標籤的下面
        var timer = document.getElementById('time');
        
        console.log(timer);
        console.log(typeof timer);
        // console.dir 打印我們返回的元素對象 更好的查看裏面的屬性和方法
        console.dir(timer);
    </script>
</body>
  • 根據標籤名獲取元素
<body>
    <ul>
        <li>知否知否,應是等你好久11</li>
        <li>知否知否,應是等你好久22</li>
    </ul>
    <ul id="nav">
        <li>生僻字</li>
        <li>生僻字</li>
    </ul>
    <script>
        // 1.返回的是 獲取過來元素對象的集合 以僞數組的形式存儲的
        var lis = document.getElementsByTagName('li');
        console.log(lis);
        console.log(lis[0]);
        // 2. 我們想要依次打印裏面的元素對象我們可以採取遍歷的方式
        for (var i = 0; i < lis.length; i++) {
            console.log(lis[i]);
        }
        // 3. element.getElementsByTagName()  可以得到這個元素裏面的某些標籤
        var nav = document.getElementById('nav'); // 這個獲得nav 元素
        var navLis = nav.getElementsByTagName('li');
        console.log(navLis);
    </script>
</body>
  • H5新增獲取元素方式
<body>
    <div class="box">盒子1</div>
    <div class="box">盒子2</div>
    <div id="nav">
        <ul>
            <li>首頁</li>
            <li>產品</li>
        </ul>
    </div>
    <script>
        // 1. getElementsByClassName 根據類名獲得某些元素集合
        var boxs = document.getElementsByClassName('box');
        console.log(boxs);
        // 2. querySelector 返回指定選擇器的第一個元素對象  切記 裏面的選擇器需要加符號 .box  #nav
        var firstBox = document.querySelector('.box');
        console.log(firstBox);
        var nav = document.querySelector('#nav');
        console.log(nav);
        var li = document.querySelector('li');
        console.log(li);
        // 3. querySelectorAll()返回指定選擇器的所有元素對象集合
        var allBox = document.querySelectorAll('.box');
        console.log(allBox);
        var lis = document.querySelectorAll('li');
        console.log(lis);
        
        document.body // 返回body元素
        document.documentElement // 返回html元素對象
        
    </script>
</body>
1.2 事件基礎
<body>
    <div>123</div>
    <script>
        // 執行事件步驟
        // 點擊div 控制檯輸出 我被選中了
        // 1. 獲取事件源
        var div = document.querySelector('div');
        // 2.綁定事件 註冊事件
        // div.onclick 
        // 3.添加事件處理程序 
        div.onclick = function() {
            console.log('我被選中了');
        }
    </script>
</body>
1.3 改變元素內容
<body>
    <div></div>
    <p>
        我是文字
        <span>123</span>
    </p>
    <script>
        // innerText 和 innerHTML的區別 
        // 1. innerText 不識別html標籤 非標準  去除空格和換行
        var div = document.querySelector('div');
        // div.innerText = '<strong>今天是:</strong> 2019';
        // 2. innerHTML 識別html標籤 W3C標準 保留空格和換行的
        div.innerHTML = '<strong>今天是:</strong> 2019';
        // 這兩個屬性是可讀寫的  可以獲取元素裏面的內容
        var p = document.querySelector('p');
        console.log(p.innerText);
        console.log(p.innerHTML);
    </script>
</body>
1.4 常用元素的屬性操作
<body>
    <button id="ldh">劉德華</button>
    <button id="zxy">張學友</button> <br>
    <img src="images/ldh.jpg" alt="" title="劉德華">
    <script>
        // 修改元素屬性  src
        // 1. 獲取元素
        var ldh = document.getElementById('ldh');
        var zxy = document.getElementById('zxy');
        var img = document.querySelector('img');
        // 2. 註冊事件  處理程序
        zxy.onclick = function() {
            img.src = 'images/zxy.jpg';
            img.title = '張學友思密達';
        }
        ldh.onclick = function() {
            img.src = 'images/ldh.jpg';
            img.title = '劉德華';
        }
        
        // 1. 獲取元素
        var btn = document.querySelector('button');
        var input = document.querySelector('input');
        // 2. 註冊事件 處理程序
        btn.onclick = function() {
            // 表單裏面的值 文字內容是通過 value 來修改的
            input.value = '被點擊了';
            // 如果想要某個表單被禁用 不能再點擊 disabled  我們想要這個按鈕 button禁用
            // btn.disabled = true;
            this.disabled = true;
            // this 指向的是事件函數的調用者 btn
        }
    </script>
</body>
1.5 樣式屬性操作
<body>
    <div></div>
    <script>
        // 1. 獲取元素
        var div = document.querySelector('div');
        // 2. 註冊事件 處理程序
        div.onclick = function() {
            // div.style裏面的屬性 採取駝峯命名法 
            this.style.backgroundColor = 'purple';
            this.style.width = '250px';
            this.className = '';
			 // this.style.backgroundColor = 'purple';
            // this.style.color = '#fff';
            // this.style.fontSize = '25px';
            // this.style.marginTop = '100px';

            // 2. 我們可以通過 修改元素的className更改元素的樣式 適合於樣式較多或者功能複雜的情況
            // 3. 如果想要保留原先的類名,我們可以這麼做 多類名選擇器
            // this.className = 'change';
            this.className = 'first change';
        }
    </script>
</body>
1.6 自定義屬性操作
<div id="demo" index="1" class="nav"></div>
<script>
    var div = document.querySelector('div');
    // 1. 獲取元素的屬性值
    // (1) element.屬性
    console.log(div.id);
    //(2) element.getAttribute('屬性')  get得到獲取 attribute 屬性的意思 我們程序員自己添加的屬性我們稱爲自定義屬性 index
    console.log(div.getAttribute('id'));
    console.log(div.getAttribute('index'));
    
    // 2. 設置元素屬性值
    // (1) element.屬性= '值'
    div.id = 'test';
    div.className = 'navs';
    // (2) element.setAttribute('屬性', '值');  主要針對於自定義屬性
    div.setAttribute('index', 2);
    div.setAttribute('class', 'footer'); // class 特殊,不是className
    // 3. 移除屬性 removeAttribute(屬性)    
    div.removeAttribute('index');
</script>
1.7 H5自定義屬性
<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
    var div = document.querySelector('div');
    // console.log(div.getTime);
    console.log(div.getAttribute('getTime'));
    div.setAttribute('data-time', 20);
    console.log(div.getAttribute('data-index'));
    console.log(div.getAttribute('data-list-name'));
    // h5新增的獲取自定義屬性的方法 它只能獲取data-開頭的
    // dataset 是一個集合裏面存放了所有以data開頭的自定義屬性
    console.log(div.dataset);
    console.log(div.dataset.index);
    console.log(div.dataset['index']);
    // 如果自定義屬性裏面有多個-鏈接的單詞,我們獲取的時候採取 駝峯命名法
    console.log(div.dataset.listName);
    console.log(div.dataset['listName']);
</script>
1.8 節點操作
// 父節點 
<div class="demo">
    <div class="box">
        <span class="erweima">×</span>
    </div>
</div>
<script>
    // 1. 父節點 parentNode
    var erweima = document.querySelector('.erweima');
    // var box = document.querySelector('.box');
    // 得到的是離元素最近的父級節點(親爸爸) 如果找不到父節點就返回爲 null
    console.log(erweima.parentNode);
</script>

// 子節點
<ul>
    <li>我是li</li>
    <li>我是li</li>
    <li>我是li</li>
    <li>我是li</li>
</ul>
<script>
    // DOM 提供的方法(API)獲取
    var ul = document.querySelector('ul');
    var lis = ul.querySelectorAll('li');
    // 1. 子節點  childNodes 所有的子節點 包含 元素節點 文本節點等等
    console.log(ul.childNodes);
    console.log(ul.childNodes[0].nodeType);
    console.log(ul.childNodes[1].nodeType);
    // 2. children 獲取所有的子元素節點 也是我們實際開發常用的
    console.log(ul.children);
</script>

<ol>
     <li>我是li1</li>
     <li>我是li2</li>
     <li>我是li3</li>
     <li>我是li4</li>
     <li>我是li5</li>
 </ol>
 <script>
     var ol = document.querySelector('ol');
     // 1. firstChild 第一個子節點 不管是文本節點還是元素節點
     console.log(ol.firstChild);
     console.log(ol.lastChild);
     // 2. firstElementChild 返回第一個子元素節點 ie9才支持
     console.log(ol.firstElementChild);
     console.log(ol.lastElementChild);
     // 3. 實際開發的寫法  既沒有兼容性問題又返回第一個子元素
     console.log(ol.children[0]);
     console.log(ol.children[ol.children.length - 1]);
 </script>

// 兄弟節點
<div>我是div</div>
<span>我是span</span>
<script>
   var div = document.querySelector('div');
   // 1.nextSibling 下一個兄弟節點 包含元素節點或者 文本節點等等
   console.log(div.nextSibling);
   console.log(div.previousSibling);
   // 2. nextElementSibling 得到下一個兄弟元素節點
   console.log(div.nextElementSibling);
   console.log(div.previousElementSibling);
</script>

// 創建添加節點
<ul>
   <li>123</li>
</ul>
<script>
   // 1. 創建節點元素節點
   var li = document.createElement('li');
   // 2. 添加節點 node.appendChild(child)  node 父級  child 是子級 後面追加元素
   var ul = document.querySelector('ul');
   ul.appendChild(li);
   // 3. 添加節點 node.insertBefore(child, 指定元素);
   var lili = document.createElement('li');
   ul.insertBefore(lili, ul.children[0]);
   // 4. 我們想要頁面添加一個新的元素 : 1. 創建元素 2. 添加元素
</script>

// 刪除節點

<button>刪除</button>
<ul>
    <li>熊大</li>
    <li>熊二</li>
    <li>光頭強</li>
</ul>
<script>
    // 1.獲取元素
    var ul = document.querySelector('ul');
    var btn = document.querySelector('button');
    // 2. 刪除元素  node.removeChild(child)
    // ul.removeChild(ul.children[0]);
    // 3. 點擊按鈕依次刪除裏面的孩子
    btn.onclick = function() {
        if (ul.children.length == 0) {
            this.disabled = true;
        } else {
            ul.removeChild(ul.children[0]);
        }
    }
</script>

// 複製(克隆)節點
<ul>
    <li>1111</li>
    <li>2</li>
    <li>3</li>
</ul>
<script>
    var ul = document.querySelector('ul');
    // 1. node.cloneNode(); 括號爲空或者裏面是false 淺拷貝 只複製標籤不復制裏面的內容
    // 2. node.cloneNode(true); 括號爲true 深拷貝 複製標籤複製裏面的內容
    var lili = ul.children[0].cloneNode(true);
    ul.appendChild(lili);
</script>

1.9 創建元素的三種方式
<script>
// 三種創建元素方式區別 
// 1. document.write() 創建元素  如果頁面文檔流加載完畢,再調用這句話會導致頁面重繪
 var btn = document.querySelector('button');
 btn.onclick = function() {
     document.write('<div>123</div>');
 }

// 2. innerHTML 創建元素
var inner = document.querySelector('.inner');
 for (var i = 0; i <= 100; i++) {
     inner.innerHTML += '<a href="#">百度</a>'
 }
var arr = [];
for (var i = 0; i <= 100; i++) {
    arr.push('<a href="#">百度</a>');
}
inner.innerHTML = arr.join('');
// 3. document.createElement() 創建元素
var create = document.querySelector('.create');
for (var i = 0; i <= 100; i++) {
    var a = document.createElement('a');
    create.appendChild(a);
}
</script>

// innerTHML和createElement效率對比

// 1. innerHTML字符串拼接方式(效率低)
<script>
    function fn() {
        var d1 = +new Date();
        var str = '';
        for (var i = 0; i < 1000; i++) {
            document.body.innerHTML += '<div style="width:100px; height:2px; border:1px solid blue;"></div>';
        }
        var d2 = +new Date();
        console.log(d2 - d1);
    }
    fn();
</script>

// 2. createElement方式(效率一般)
<script>
    function fn() {
        var d1 = +new Date();

        for (var i = 0; i < 1000; i++) {
            var div = document.createElement('div');
            div.style.width = '100px';
            div.style.height = '2px';
            div.style.border = '1px solid red';
            document.body.appendChild(div);
        }
        var d2 = +new Date();
        console.log(d2 - d1);
    }
    fn();
</script>

// 3. innerHTML數組方式(效率高)
<script>
    function fn() {
        var d1 = +new Date();
        var array = [];
        for (var i = 0; i < 1000; i++) {
            array.push('<div style="width:100px; height:2px; border:1px solid blue;"></div>');
        }
        document.body.innerHTML = array.join('');
        var d2 = +new Date();
        console.log(d2 - d1);
    }
    
fn();
</script>

1.91 事件高級
1.91.1 事件監聽

addEventListener()事件監聽(IE9以後支持)
attacheEvent()事件監聽(IE678支持)

<button>傳統註冊事件</button>
<button>方法監聽註冊事件</button>
<button>ie9 attachEvent</button>
<script>
    var btns = document.querySelectorAll('button');
    // 1. 傳統方式註冊事件
    btns[0].onclick = function() {
        alert('hi');
    }
    btns[0].onclick = function() {
            alert('hao a u');
        }
   // 2. 事件偵聽註冊事件 addEventListener 
   // (1) 裏面的事件類型是字符串 必定加引號 而且不帶on
   // (2) 同一個元素 同一個事件可以添加多個偵聽器(事件處理程序)
    btns[1].addEventListener('click', function() {
        alert(22);
    })
    btns[1].addEventListener('click', function() {
            alert(33);
    })
    // 3. attachEvent ie9以前的版本支持
    btns[2].attachEvent('onclick', function() {
        alert(11);
    })
</script>
1.91.2 刪除事件(解綁事件)
<div>1</div>
<div>2</div>
<div>3</div>
<script>
   var divs = document.querySelectorAll('div');
   divs[0].onclick = function() {
       alert(11);
       // 1. 傳統方式刪除事件
       divs[0].onclick = null;
   }
   // 2. removeEventListener 刪除事件
   divs[1].addEventListener('click', fn) // 裏面的fn 不需要調用加小括號
   function fn() {
       alert(22);
       divs[1].removeEventListener('click', fn);
   }
   // 3. detachEvent
   divs[2].attachEvent('onclick', fn1);

   function fn1() {
       alert(33);
       divs[2].detachEvent('onclick', fn1);
   }
</script>
1.91.3 事件冒泡與捕獲
// 事件冒泡
<div class="father">
   <div class="son">son盒子</div>
</div>
<script>
   // onclick 和 attachEvent(ie) 在冒泡階段觸發
   // 冒泡階段 如果addEventListener 第三個參數是 false 或者 省略 
   // son -> father ->body -> html -> document
   var son = document.querySelector('.son');
// 給son註冊單擊事件
   son.addEventListener('click', function() {
       alert('son');
   }, false);
// 給father註冊單擊事件
   var father = document.querySelector('.father');
   father.addEventListener('click', function() {
       alert('father');
   }, false);
// 給document註冊單擊事件,省略第3個參數
   document.addEventListener('click', function() {
       alert('document');
   })
</script>

// 事件捕獲
<div class="father">
    <div class="son">son盒子</div>
</div>
<script>
    // 如果addEventListener() 第三個參數是 true 那麼在捕獲階段觸發
    // document -> html -> body -> father -> son
     var son = document.querySelector('.son');
// 給son註冊單擊事件,第3個參數爲true
     son.addEventListener('click', function() {
         alert('son');
     }, true);
     var father = document.querySelector('.father');
// 給father註冊單擊事件,第3個參數爲true
     father.addEventListener('click', function() {
         alert('father');
     }, true);
// 給document註冊單擊事件,第3個參數爲true
    document.addEventListener('click', function() {
        alert('document');
    }, true)
</script>

1.91.4 事件對象

事件發生後,跟事件相關的一系列信息數據的集合都放到這個對象裏面,這個對象就是事件對象。
誰綁定了這個事件,鼠標觸發事件的話,會得到鼠標的相關信息,如鼠標位置,鍵盤觸發事件的話,會得到鍵盤的相關信息,如按了哪個鍵。事件觸發發生時就會產生事件對象,並且系統會以實參的形式傳給事件處理函數。所以,在事件處理函數中聲明1個形參用來接收事件對象。

  • 事件對象的兼容性處理

事件對象本身的獲取存在兼容問題:
1.標準瀏覽器中是瀏覽器給方法傳遞的參數,只需要定義形參 e 就可以獲取到。
2.在 IE6~8 中,瀏覽器不會給方法傳遞參數,如果需要的話,需要到 window.event 中獲取查找。
只要“||”前面爲false, 不管“||”後面是true 還是 false,都返回 “||” 後面的值。
只要“||”前面爲true, 不管“||”後面是true 還是 false,都返回 “||” 前面的值。

<div>123</div>
<script>
    var div = document.querySelector('div');
    div.onclick = function(e) {
            // 事件對象
            e = e || window.event;
            console.log(e);
    }
</script>
  • e.target 和 this 的區別

this 是事件綁定的元素(綁定這個事件處理函數的元素) 。e.target 是事件觸發的元素。常情況下terget 和 this是一致的,但有一種情況不同,那就是在事件冒泡時(父子元素有相同事件,單擊子元素,父元素的事件處理函數也會被觸發執行),這時候this指向的是父元素,因爲它是綁定事件的元素對象,而target指向的是子元素,因爲他是觸發事件的那個具體元素對象。

<div>123</div>
<script>
    var div = document.querySelector('div');
    div.addEventListener('click', function(e) {
        // e.target 和 this指向的都是div
        console.log(e.target);
        console.log(this);

    });
</script>
  • 事件冒泡下的e.target和this
<ul>
    <li>abc</li>
    <li>abc</li>
    <li>abc</li>
</ul>
<script>
    var ul = document.querySelector('ul');
    ul.addEventListener('click', function(e) {
          // 我們給ul 綁定了事件  那麼this 就指向ul  
          console.log(this); // ul

          // e.target 觸發了事件的對象 我們點擊的是li e.target 指向的就是li
          console.log(e.target); // li
    });
</script>
  • 阻止默認行爲

html中一些標籤有默認行爲,例如a標籤被單擊後,默認會進行頁面跳轉。

<a href="http://www.baidu.com">百度</a>
<script>

    // 2. 阻止默認行爲 讓鏈接不跳轉 
    var a = document.querySelector('a');
    a.addEventListener('click', function(e) {
         e.preventDefault(); //  dom 標準寫法
    });
    
    // 3. 傳統的註冊方式
    a.onclick = function(e) {
        // 普通瀏覽器 e.preventDefault();  方法
        e.preventDefault();
        // 低版本瀏覽器 ie678  returnValue  屬性
        e.returnValue = false;
        // 我們可以利用return false 也能阻止默認行爲 沒有兼容性問題
        return false;
    }
</script>
  • 阻止事件冒泡
<div class="father">
    <div class="son">son兒子</div>
</div>
<script>
    var son = document.querySelector('.son');
	// 給son註冊單擊事件
    son.addEventListener('click', function(e) {
        alert('son');
        e.stopPropagation(); // stop停止Propagation 傳播
        window.event.cancelBubble = true; // 非標準 cancel 取消 bubble 泡泡
    }, false);

    var father = document.querySelector('.father');
    
	// 給father註冊單擊事件
    father.addEventListener('click', function() {
        alert('father');
    }, false);
    
	// 給document註冊單擊事件
    document.addEventListener('click', function() {
        alert('document');
    })
</script>
1.91.5 事件委託

事件委託也稱爲事件代理,在 jQuery 裏面稱爲事件委派。不給子元素註冊事件,給父元素註冊事件,把處理代碼在父元素的事件中執行。給父元素註冊事件,利用事件冒泡,當子元素的事件觸發,會冒泡到父元素,然後去控制相應的子元素。

  • 事件委託的作用

我們只操作了一次 DOM ,提高了程序的性能。動態新創建的子元素,也擁有事件。

<ul>
    <li>知否知否,點我應有彈框在手!</li>
    <li>知否知否,點我應有彈框在手!</li>
    <li>知否知否,點我應有彈框在手!</li>
    <li>知否知否,點我應有彈框在手!</li>
    <li>知否知否,點我應有彈框在手!</li>
</ul>
<script>
    // 事件委託的核心原理:給父節點添加偵聽器, 利用事件冒泡影響每一個子節點
    var ul = document.querySelector('ul');
    ul.addEventListener('click', function(e) {
        // e.target 這個可以得到我們點擊的對象
        e.target.style.backgroundColor = 'pink';
    })
</script>
1.91.6 鼠標事件
  • 禁止選中文字和禁止右鍵菜單
<body>
    我是一段不願意分享的文字
    <script>
        // 1. contextmenu 我們可以禁用右鍵菜單
        document.addEventListener('contextmenu', function(e) {
                e.preventDefault();
        })
        // 2. 禁止選中文字 selectstart
        document.addEventListener('selectstart', function(e) {
            e.preventDefault();
        })
    </script>
</body>
  • 獲取鼠標在頁面的座標
<script>
    // 鼠標事件對象 MouseEvent
    document.addEventListener('click', function(e) {
        // 1. client 鼠標在可視區的x和y座標
        console.log(e.clientX);
        console.log(e.clientY);
        console.log('---------------------');

        // 2. page 鼠標在頁面文檔的x和y座標
        console.log(e.pageX);
        console.log(e.pageY);
        console.log('---------------------');

        // 3. screen 鼠標在電腦屏幕的x和y座標
        console.log(e.screenX);
        console.log(e.screenY);

    })
</script>
1.91.7 鍵盤事件
<script>
    // 常用的鍵盤事件
    //1. keyup 按鍵彈起的時候觸發 
    document.addEventListener('keyup', function() {
        console.log('我彈起了');
    })

    //3. keypress 按鍵按下的時候觸發  不能識別功能鍵 比如 ctrl shift 左右箭頭啊
    document.addEventListener('keypress', function() {
            console.log('我按下了press');
    })
    //2. keydown 按鍵按下的時候觸發  能識別功能鍵 比如 ctrl shift 左右箭頭啊
    document.addEventListener('keydown', function() {
            console.log('我按下了down');
    })
    // 4. 三個事件的執行順序  keydown -- keypress -- keyup
</script>
  • 使用keyCode屬性判斷用戶按下哪個鍵**
<script>
    // 鍵盤事件對象中的keyCode屬性可以得到相應鍵的ASCII碼值
    document.addEventListener('keyup', function(e) {
        console.log('up:' + e.keyCode);
        // 我們可以利用keycode返回的ASCII碼值來判斷用戶按下了那個鍵
        if (e.keyCode === 65) {
            alert('您按下的a鍵');
        } else {
            alert('您沒有按下a鍵')
        }
    })
    document.addEventListener('keypress', function(e) {
        // console.log(e);
        console.log('press:' + e.keyCode);
    })
</script>

2. BOM瀏覽器對象模型

BOM(Browser Object Model)即瀏覽器對象模型,它提供了獨立於內容而與瀏覽器窗口進行交互的對象,其核心對象是 window。BOM 由一系列相關的對象構成,並且每個對象都提供了很多方法與屬性。BOM 缺乏標準,JavaScript 語法的標準化組織是 ECMA,DOM 的標準化組織是 W3C,BOM 最初是Netscape 瀏覽器標準的一部分。

2.1 頂級對象window
2.1.1 頁面(窗口)加載事件

window.onload 是窗口 (頁面)加載事件,當文檔內容完全加載完成會觸發該事件(包括圖像、腳本文件、CSS 文件等), 就調用的處理函數。DOMContentLoaded 事件觸發時,僅當DOM加載完成,不包括樣式表,圖片,flash等等。IE9以上才支持。


<script>
    window.addEventListener('load', function() {
        var btn = document.querySelector('button');
        btn.addEventListener('click', function() {
            alert('點擊我');
        })
    })
    window.addEventListener('load', function() {
        alert(22);
    })
    document.addEventListener('DOMContentLoaded', function() {
        alert(33);
    })
</script>
2.1.2 調整窗口大小事件

window.onresize 是調整窗口大小加載事件, 當觸發時就調用的處理函數。1.只要窗口大小發生像素變化,就會觸發這個事件。2.我們經常利用這個事件完成響應式佈局。 window.innerWidth 當前屏幕的寬度

<script>
    // 註冊頁面加載事件
    window.addEventListener('load', function() {
        var div = document.querySelector('div');
    	// 註冊調整窗口大小事件
        window.addEventListener('resize', function() {
            // window.innerWidth 獲取窗口大小
            console.log('變化了');
            if (window.innerWidth <= 800) {
                div.style.display = 'none';
            } else {
                div.style.display = 'block';
            }
        })
    })
</script>
<div></div>
2.1.3 定時器(兩種)

window 對象給我們提供了 2 個非常好用的方法-定時器。 setTimeout() 和 setInterval()

<script>
    // 回調函數是一個匿名函數
     setTimeout(function() {
         console.log('時間到了');

     }, 2000);
    function callback() {
        console.log('爆炸了');
    }
// 回調函數是一個有名函數
    var timer1 = setTimeout(callback, 3000);
    var timer2 = setTimeout(callback, 5000);
</script>

// 5秒後關閉一個廣告
<body>
    <img src="images/ad.jpg" alt="" class="ad">
    <script>
        // 獲取要操作的元素
        var ad = document.querySelector('.ad');
		// 開啓定時器
        setTimeout(function() {
            ad.style.display = 'none';
        }, 5000);
    </script>
</body>

<button>點擊停止定時器</button>
<script>
    var btn = document.querySelector('button');
	// 開啓定時器
    var timer = setTimeout(function() {
        console.log('爆炸了');
    }, 5000);
	// 給按鈕註冊單擊事件
    btn.addEventListener('click', function() {
        // 停止定時器
        clearTimeout(timer);
    })
</script>

// setInterval() 鬧鐘定時器
<script>
    // 1. setInterval 
    setInterval(function() {
        console.log('繼續輸出');
    }, 1000);
</script>

// clearInterval(timer)停止定時器
手機號碼: <input type="number"> <button>發送</button>
<script>
var btn = document.querySelector('button');
// 全局變量,定義剩下的秒數
var time = 3; 
// 註冊單擊事件
btn.addEventListener('click', function() {
   // 禁用按鈕
   btn.disabled = true;
   // 開啓定時器
   var timer = setInterval(function() {
       // 判斷剩餘秒數
       if (time == 0) {
           // 清除定時器和復原按鈕
           clearInterval(timer);
           btn.disabled = false;
           btn.innerHTML = '發送';
       } else {
           btn.innerHTML = '還剩下' + time + '秒';
           time--;
       }
   }, 1000);
});
</script>
2.1.4 this指向問題

this的指向在函數定義的時候是確定不了的,只有函數執行的時候才能確定this到底指向誰,一般情況下this的最終指向的是那個調用它的對象。
1.全局作用域或者普通函數中this指向全局對象window(注意定時器裏面的this指向window)
2.方法調用中誰調用this指向誰
3.構造函數中this指向構造函數的實例


<button>點擊</button>
<script>
    // this 指向問題 一般情況下this的最終指向的是那個調用它的對象
    // 1. 全局作用域或者普通函數中this指向全局對象window( 注意定時器裏面的this指向window)
    console.log(this);
    function fn() {
        console.log(this);
    }
    window.fn();
    window.setTimeout(function() {
        console.log(this);
    }, 1000);
    // 2. 方法調用中誰調用this指向誰
    var o = {
        sayHi: function() {
            console.log(this); // this指向的是 o 這個對象
        }
    }
    o.sayHi();
    var btn = document.querySelector('button');
    btn.addEventListener('click', function() {
            console.log(this); // 事件處理函數中的this指向的是btn這個按鈕對象
        })
    // 3. 構造函數中this指向構造函數的實例
    function Fun() {
        console.log(this); // this 指向的是fun 實例對象
    }
    var fun = new Fun();
</script>
2.2 location對象
// 5分鐘自動跳轉頁面
<button>點擊</button>
<div></div>
<script>
   var btn = document.querySelector('button');
   var div = document.querySelector('div');
   btn.addEventListener('click', function() {
       // console.log(location.href);
       location.href = 'http://www.itcast.cn';
   })
   var timer = 5;
   setInterval(function() {
       if (timer == 0) {
           location.href = 'http://www.itcast.cn';
       } else {
           div.innerHTML = '您將在' + timer + '秒鐘之後跳轉到首頁';
           timer--;
       }
   }, 1000);
</script>

// 獲取URL參數
<div></div>
<script>
    console.log(location.search); // ?uname=andy
    // 1.先去掉?  substr('起始的位置',截取幾個字符);
    var params = location.search.substr(1); // uname=andy
    console.log(params);
    // 2. 利用=把字符串分割爲數組 split('=');
    var arr = params.split('=');
    console.log(arr); // ["uname", "ANDY"]
    var div = document.querySelector('div');
    // 3.把數據寫入div中
    div.innerHTML = arr[1] + '歡迎您';
</script>

<button>點擊</button>
<script>
    var btn = document.querySelector('button');
    btn.addEventListener('click', function() {
        // 記錄瀏覽歷史,所以可以實現後退功能
        // location.assign('http://www.itcast.cn');
        // 不記錄瀏覽歷史,所以不可以實現後退功能
        // location.replace('http://www.itcast.cn');
        location.reload(true);
    })
</script>

2.3 navigator對象

navigator 對象包含有關瀏覽器的信息,它有很多屬性,我們最常用的是 userAgent,該屬性可以返回由客戶機發送服務器的 user-agent 頭部的值。下面前端代碼可以判斷用戶那個終端打開頁面,實現跳轉。

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
    window.location.href = "";     //手機
 } else {
    window.location.href = "";     //電腦
 }
2.3 history對象

window對象給我們提供了一個 history對象,與瀏覽器歷史記錄進行交互。該對象包含用戶(在瀏覽器窗口中)訪問過的URL。

back() //後退
forward() // 前進
go(參數) // 1:前進一個頁面 -1: 後對一個頁面

3. Js執行機制

JS 是單線程的, 單線程就意味着,所有任務需要排隊,前一個任務結束,纔會執行後一個任務。如果前一個任務耗時很長,後一個任務就不得不一直等着。這樣所導致的問題是: 如果 JS 執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞的感覺。​ 爲了解決這個問題,利用多核 CPU 的計算能力,HTML5 提出 Web Worker 標準,允許 JavaScript 腳本創建多個線程,但是子線程完全受主線程控制。於是,JS 中出現了同步任務異步任務

4. offset/client/scroll

1.元素偏移量offset系列 經常用於獲得元素位置 offsetLeft offsetTop
offset 與 style 區別

  • offset 可以得到任意樣式表中的樣式值
  • offset 系列獲得的數值是沒有單位的
  • offsetWidth 包含padding+border+width
  • offsetWidth 等屬性是隻讀屬性,只能獲取不能賦值
    所以,我們想要獲取元素大小位置,用offset更合適
  • style 只能得到行內樣式表中的樣式值
  • style.width 獲得的是帶有單位的字符串
  • style.width 獲得不包含padding和border 的值
  • style.width 是可讀寫屬性,可以獲取也可以賦值
    所以,我們想要給元素更改值,則需要用style改變

2.元素可視區client經常用於獲取元素大小 clientWidth clientHeight
client 翻譯過來就是客戶端,我們使用 client 系列的相關屬性來獲取元素可視區的相關信息。通過 client系列的相關屬性可以動態的得到該元素的邊框大小、元素大小等。
3.元素滾動scroll 經常用於獲取滾動距離 scrollTop scrollLeft
scroll 翻譯過來就是滾動的,我們使用 scroll 系列的相關屬性可以動態的得到該元素的大小、滾動距離等。

4.注意頁面滾動的距離通過 window.pageXOffset 獲得

5. mouseenter 和mouseover的區別

  • 當鼠標移動到元素上時就會觸發mouseenter 事件
  • 類似 mouseover,它們兩者之間的差別是
  • mouseover 鼠標經過自身盒子會觸發,經過子盒子還會觸發。mouseenter 只會經過自身盒子觸發
  • 之所以這樣,就是因爲mouseenter不會冒泡
  • 跟mouseenter搭配鼠標離開 mouseleave 同樣不會冒泡

6. 觸屏事件

touchstart、touchmove、touchend可以實現拖動元素
但是拖動元素需要當前手指的座標值 我們可以使用 targetTouches[0] 裏面的pageX 和 pageY
移動端拖動的原理:
手指移動中,計算出手指移動的距離。然後用盒子原來的位置 + 手指移動的距離
手指移動的距離: 手指滑動中的位置 減去 手指剛開始觸摸的位置
拖動元素三步曲:
(1) 觸摸元素 touchstart: 獲取手指初始座標,同時獲得盒子原來的位置
(2) 移動手指 touchmove: 計算手指的滑動距離,並且移動盒子
(3) 離開手指 touchend:
手指移動也會觸發滾動屏幕所以這裏要阻止默認的屏幕滾動 e.preventDefault();

7. 本地存儲

隨着互聯網的快速發展,基於網頁的應用越來越普遍,同時也變的越來越複雜,爲了滿足各種各樣的需求,會經常性在本地存儲大量的數據,HTML5規範提出了相關解決方案。

  • 本地存儲特性

1、數據存儲在用戶瀏覽器中
2、設置、讀取方便、甚至頁面刷新不丟失數據
3、容量較大,sessionStorage約5M、localStorage約20M
4、只能存儲字符串,可以將對象JSON.stringify() 編碼後存儲

  • window.sessionStorage

1、生命週期爲關閉瀏覽器窗口
2、在同一個窗口(頁面)下數據可以共享
3、以鍵值對的形式存儲使用

sessionStorage.setItem(key, value)
sessionStorage.getItem(key)
sessionStorage.removeItem(key)
sessionStorage.clear()
  • window.localStorage

1、聲明週期永久生效,除非手動刪除 否則關閉頁面也會存在
2、可以多窗口(頁面)共享(同一瀏覽器可以共享)
3、 以鍵值對的形式存儲使用

localStorage.setItem(key, value)
localStorage.getItem(key)
localStorage.removeItem(key)
localStorage.clear()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章