Dom、事件

問答

一、dom對象的innerText和innerHTML有什么區別?

  • innerText
    innerText是一個可寫屬性,返回元素內包含的文本內容,在多層次的時候會按照元素由淺到深的順序拼接其內容。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>innerText</title>
</head>
<body>
  <div>
    <p>
      123
      <span>456</span>
    </p>
  </div>
</body>
</html>

外層div的innerText返回內容是 "123456"


innerText
  • innerHTML
    innerHTML和innerText的作用類似,但是它不是返回元素的文本內容,而是返回元素的HTML結構。


    innerHTML

二、elem.children和elem.childNodes的區別?

  • elem.children
    elem.children是一個只讀屬性,對象類型為HTMLCollection
    ,返回一個包含當前元素的子元素的集合。非元素的部分,比如空格、換行、或者單純的文字不返回(文本節點以外的其他HTML節點)。
  • elem.chilNodes
    elem.chilNodes是獲取包括文本節點的所有子元素列表(NodeList)。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Element</title>
</head>
<body>
  <div>
    <p id="desp">
      <span>1</span>
    </p>
    <!-- <p class="desp">段落2<span>2</span></p>
    <p class="desp">段落3<span>3</span></p> -->
  </div>
  <script>
    var p = document.getElementById('desp');
    console.log(p);
    console.log(p.children);
    console.log(p.children[0]);
    console.log(p.childNodes);
    console.log(p.childNodes[0]);
  </script>
</body>
</html>
對比

一般來說,elem.children更穩妥一些。如上面結果所示,使用elem.chilNodes獲取的第一個元素不是span,而是回車符(相當于文本字符)。

三、查詢元素有幾種常見的方法?

  • getElementById()
    返回匹配指定ID屬性的元素節點,如果沒有匹配的節點,則返回null。這是獲取元素最快的方法。
var elem = document.getElementById('ct');
  • getElementsByClassName()
    返回一個類似數組的對象(HTMLCollection類型的對象),包括了所有class名字符合指定條件的元素(搜索范圍包括本身),元素的變化實時反映在返回結果中。這個方法不僅可以在document對象上調用,也可以在任何元素節點上調用。
var elements = document.getElementsByClassName('desp');

getElementsByClassName方法的參數,可以是多個空格分隔的class名字,返回同時具有這些節點的元素。

var elements = document.getElementsByClassName('test desp');
  • getElementsByTagName()
    返回所有指定標簽的元素(搜索范圍包括本身),返回值是一個HTMLCollection對象,也就是說,搜索結果是一個動態集合,任何元素的變化都會實時反映在返回的集合中。這個方法不僅可以在document對象上調用,也可以在任何元素節點上調用。注意:此方法會將參數轉換為小寫后再進行搜索。
var elements = document.getElementsByTagName('p');
  • getElementsByName()
    返回具有name屬性的HTML元素,比如form、img、frame、embed和object,返回NodeList格式的對象,也就是說不會實時的反應元素的變化。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
    <form name="myForm" action="/test/6.php" method="post">
        姓名:<input name="username" type="text" placeholder="用戶名" value="hello" maxlength=10 />  <br/>
        密碼:<input name="pwd" type="text" placeholder="密碼" maxlength=10 disabled />  <br/>
        性別:<input type="radio" name="sex" value="male" /> 男
              <input type="radio" name="sex" value="female" /> 女 <br/>
        愛好:<input type="checkbox" name="bike" checked />自行車
              <input type="checkbox" name="car" checked />汽車
    </form>
  <script>
    var forms = document.getElementsByName("username");
    console.log(forms);
    console.log(forms[0].tagName);
  </script>
</body>
</html>
結果

注意:在IE瀏覽器使用這個方法,會將沒有name屬性、但有同名id屬性的元素也返回,所以name和id屬性最好設為不一樣的值。

  • querySelector()
    返回匹配指定CSS選擇器的元素節點。如果有多個節點滿足匹配條件,則返回第一個匹配的節點。如果沒有匹配的節點,則返回null。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div class="user-panel main">
    <input name="login"/>
</div>
<script>
    var el = document.querySelector("div.user-panel input[name=login]");
    console.log(el);
</script>
</body>
</html>
input標簽被打印
  • querySelectorAll()
    返回匹配指定CSS選擇器的所有節點,返回的是NodeList類型的對象。
var matches = document.querySelectorAll("div.note, div.alert"); // 返回class屬性為note或者alert的div元素
  • elementFromPoint()
    返回位于頁面指定位置的元素。如果該元素不可返回(比如文本框的滾動條),則返回它的父元素;如果坐標無意義,則返回null。
var ele = document.elementFromPoint(x, y); // x,y分別是相對于當前窗口左上角的橫坐標和縱坐標,單位是CSS像素。

四、如何創建一個元素?如何給元素設置屬性?

1、創建元素

  • createElement()
    createElement用來生成HTML元素節點,參數為元素的標簽名,即元素的tagName屬性。如果傳入的為大寫的標簽名,則會被轉換為小寫。如果參數帶有尖括號(即<和>)或者是null,會報錯。
var newDiv = document.createElement('div');
  • createTextNode()
    用來生成文本節點,參數為文本節點的內容。
var newDiv = document.createElement('div');
var newContent = document.createTextNode('我是div');
  • createDocumentFragment()
    用于生成一個DocumentFragment對象。DocumentFragment可以提供一個緩沖的機制,將DOM節點先放到內存中,當節點都構造完成后,再將DocumentFragment對象添加到頁面中,這時所有的節點都會一次渲染出來,這樣就能減少瀏覽器很多的負擔,明顯的提高頁面渲染速度。
var fragment = document.createDocumentFragment();

2、給元素設置屬性
setAttribute()可以用來給元素設置屬性。

  <div id='ct'>Hello</div>
  <script>
    var el = document.getElementById('ct');
    el.setAttribute('myAttribute', 'newVal');
  </script>

五、元素的添加、刪除?

1、元素的添加

  • appendChild()
    用于向節點添加最后一個子節點。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <ul class="ct">
      <li class="item"><span class="s">1</span>1</li>
      <li class="item"><span class="s">4</span>4</li>
      <li class="item"><span class="s">3</span>3</li>
      <li class="item"><span class="s">2</span>2</li>
    </ul>
</body>
<script>
    var items = document.querySelectorAll('.item');
    var itemsArr = [];
    for(var i=0;i<items.length;i++)
    {
      itemsArr.push(items[i]);
    }
    itemsArr.sort(function(a, b){
      return parseInt(a.children[0].innerText) - parseInt(b.children[0].innerText);
    })
    for(var i=0;i<itemsArr.length;i++)
    {
      document.querySelector('.ct').appendChild(itemsArr[i]);
    }
</script>
</html>
  • insertBefore()
    在某個元素之前插入元素。
<div id="ct">
    <p>1</p>
    <p>2</p>
</div>
<script>
    var span = document.createElement('span');
    var el = document.getElementById('ct');
    el.insertBefore(span, el.firstChild); // 在<p>1</p>前插入
</script>

2、元素的刪除
removeChild()

六、DOM0 事件和DOM2級在事件監聽使用方式上有什么區別?

  • DOM0
    DOM0級事件處理程序是將一個函數賦值給一個事件處理程序屬性,而通過將事件處理程序設置為null刪除綁定在元素上的事件處理程序。無法給一個事件添加多個事件處理程序,后面的程序會覆蓋前面的程序。
<input id='btn' type='button' value='click me...' />

<script type="text/javascript">
  var btnClick = document.getElementById('btn');
  // 添加事件處理程序
  btnClick.onclick = function () {
    alert (this.id);
  };
  // 刪除事件處理程序
  btnClick.onclick = null;
</script>
  • DOM2
    DOM2級事件定義了兩個方法用于添加和刪除事件處理程序的操作:addEventListenerremoveEventListener。所有DOM節點都包含這兩個方法,它們接受三個參數:事件類型、事件處理方法、布爾參數(true,表示在捕獲階段調用事件處理程序;false:表示在事件冒泡階段處理)。
<input id='btn' typ='button' value='click me...' />
 <script type="text/javascript">
    var btnClick = document.querySelector('#btn');
    btnClick.addEventListener('click', function(){
      alert(this.id);
    }, false);
  // 可以為click事件添加多個處理程序
  btnClick.addEventListener('click', function(){
    alert('Hello');
}, false);
</script>

通過addEventListener添加的事件處理程序只能通過removeListener移除,移除時參數與添加的時候相同,這就意味著剛才我們添加的匿名函數無法移除。因為匿名函數雖然方法體一樣,但是句柄卻不相同。所以可以如下實現:

<input id="btn" type="button" value="Click Here" />
<script type="text/javascript">
    var btnClick = document.getElementById('btn');
    var handler=function() {
        alert(this.id);
    }
    btnClick.addEventListener('click', handler, false);
    btnClick.removeEventListener('click', handler, false);
</script>

七、attachEvent與addEventListener的區別?

IE不支持addEventListener和removeListener,而是實現了兩個類似的方法:attachEvent和detachEvent。
attachEvent與addEventListener的區別:

  • 參數個數不同
    addEventListener有三個參數,attachEvent只有兩個。attachEvent添加事件處理程序只能發生在冒泡階段,addEventListener第三個參數可以決定添加的事件處理程序是在捕獲階段還是冒泡階段處理。
  • 第一個參數意義不同
    addEventListener第一個參數是事件類型(click),而attachEvent第一個參數是事件處理函數名稱(onclick)。
  • 事件處理程序的作用域不相同
    addEventListener作用域是元素本身,this指的是觸發的元素。而attachEvent事件處理程序會在全局變量內運行,事件處理程序會在全局變量內運行。
  • 為一個事件添加多個事件處理程序時,執行順序不同
    addEventListener添加會按照添加順序執行,而attachEvent添加多個事件處理程序時順序無規律。

八、解釋IE事件冒泡和DOM2事件傳播機制?

  • IE事件冒泡
    事件由最具體的元素接收,然后逐級向上傳播到較為不具體的元素。
  • DOM2事件傳播機制
    DOM2事件規定事件流包括三個階段:事件捕獲階段、處于目標階段、事件冒泡階段。首先發生的是事件捕獲階段,為截取事件提供機會,然后是實際目標接收事件,最后是冒泡階段。

九、如何阻止事件冒泡? 如何阻止默認事件?

  • 阻止事件冒泡
    當bubbles為true時,可以通過stopPropagation()方法阻止事件冒泡。
  • 阻止默認事件
    當cancelable為true時,可以通過preventDefault()方法阻止默認事件。
<div id="ct">
  <button id="btn">點我</button>
  <a id='link' target="_blank" href='www.baidu.com'>百度</a>
</div>
<script type="text/javascript">
  var wrap = document.querySelector('#ct');
  var btn = document.querySelector('#btn');
  var link = document.querySelector('#link');
  wrap.addEventListener('click', function(e){
    console.log(this.id);
  }, false);
  btn.addEventListener('click', function(e){
    console.log(this.id);
    e.stopPropagation();
  }, false);
  link.addEventListener('click', function(e){
    console.log(this.id);
    e.preventDefault();
  }, false);
</script>

代碼

一、有如下代碼,要求當點擊每一個元素li時控制臺展示該元素的文本內容。不考慮兼容

<ul class="ct">
    <li>蘋果</li>
    <li>橘子</li>
    <li>香蕉</li>
</ul>
<script>
//todo ...
</script>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>one</title>
</head>
<body>
  <ul class="ct">
    <li>蘋果</li>
    <li>橘子</li>
    <li>香蕉</li>
</ul>
<script>
  var ct = document.getElementsByClassName('ct')[0];
  ct.addEventListener('click', function(e){
    console.log(e.target.innerText);
  }, false);
</script>
</body>
</html>

二、補全代碼,要求:

  • 當點擊按鈕開頭添加時在<li>蘋果</li>元素前添加一個新元素,內容為用戶輸入的非空字符串;當點擊結尾添加時在<li>香蕉</li>后添加用戶輸入的非空字符串.
  • 當點擊每一個元素li時控制臺展示該元素的文本內容。
<ul class="ct">
    <li>蘋果</li>
    <li>橘子</li>
    <li>香蕉</li>
</ul>
<input class="ipt-add-content" placeholder="添加內容"/>
<button id="btn-add-start">開頭添加</button>
<button id="btn-add-end">結尾添加</button>
<script>
//todo ...
</script>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>second</title>
</head>
<body>
  <ul class="ct">
    <li>蘋果</li>
    <li>橘子</li>
    <li>香蕉</li>
  </ul>
  <input class="ipt-add-content" placeholder="添加內容"/>
  <button id="btn-add-start">開頭添加</button>
  <button id="btn-add-end">結尾添加</button>
  <script>
    // 獲取input的輸入值
    var value;
    var input = document.getElementsByClassName('ipt-add-content')[0];
    input.addEventListener('change', function(e){
      value = e.target.value;
    }, false);
    document.body.addEventListener('click', function(e){
      // 增加元素
      var ct = document.getElementsByClassName('ct')[0];
      var li = document.createElement('li');
      var content = document.createTextNode(value);
      li.appendChild(content);
      if(e.target.id == 'btn-add-start')
      {
        var addStart = document.getElementById('btn-add-start');
        var eleStart =  ct.children[0];
        if(!value)
        {
          alert('輸入內容不能為空');
          return;
        }
        ct.insertBefore(li, eleStart);
      }
      if(e.target.id == 'btn-add-end')
      {
        if(!value)
        {
          alert('輸入內容不能為空');
          return;
        }
        ct.appendChild(li);
      }
      console.log(e);
      // 點擊li打印文本內容
      if(e.target.tagName.toLowerCase() == 'li')
      {
        console.log(e.target.innerText);
      }
    }, false);
  </script>
</body>
</html>

預覽

三、補全代碼,要求:當鼠標放置在li元素上,會在img-preview里展示當前li元素的data-img對應的圖片。

<ul class="ct">
    <li data-img="1.png">鼠標放置查看圖片1</li>
    <li data-img="2.png">鼠標放置查看圖片2</li>
    <li data-img="3.png">鼠標放置查看圖片3</li>
</ul>
<div class="img-preview"></div>
<script>
//todo ...
</script>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>third</title>
</head>
<body>
  <ul class="ct">
    <li data-img="http://ww3.sinaimg.cn/bmiddle/68bf4cd7ly1fb9899g6bij226k3vj7wp.jpg">鼠標放置查看圖片1</li>
    <li data-img="http://ww2.sinaimg.cn/bmiddle/68bf4cd7ly1fb98bn69t6j21111trqva.jpg">鼠標放置查看圖片2</li>
    <li data-img="http://ww3.sinaimg.cn/bmiddle/68bf4cd7ly1fb98bzvmzbj21ww2pfe82.jpg">鼠標放置查看圖片3</li>
</ul>
<div class="img-preview"></div>
<script>
  var ct = document.querySelector('.ct');
  console.log(ct);
  var preview = document.querySelector('.img-preview');
  ct.addEventListener('mouseover', function(e){
    var url = e.target.getAttribute('data-img');
    preview.innerHTML = `<img src= "${url}" />`;
  }, false);
</script>
</body>
</html>

預覽

四、實現如下圖Tab切換的功能。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>fourth</title>
  <style>
    html, body, ul, li{
      margin: 0;
      padding: 0;
    }
    li{
      list-style: none;
    }
    a{
      text-decoration: none;
      color: black;
    }
    .ct{
      height: 210px;
      width: 600px;
      border: 2px solid #ccc;
      font-weight: 600;
    }
    .nav > li{
      float: left;
      width: 200px;
      line-height: 30px;
      border-bottom: 2px solid #ccc;
      text-align: center;
    }
    .nav>li:hover{
      background: #ededed;
    }
  </style>
</head>
<body>
  <div class='ct'>
    <ul class='nav'>
      <li><a href='#'>tab1</a></li>
      <li><a href="#">tab2</a></li>
      <li><a href="#">tab3</a></li>
    </ul>
    <div class='content'>內容1</div>
  </div>
  <script>
    var tab = document.querySelector('.ct');
    var contentTag = document.querySelector('.content');
    tab.addEventListener('click', function(e){
      var value = e.target.innerText;
      switch(value)
      {
        case 'tab1':
          contentTag.innerText = '內容1';
          break;
        case 'tab2':
          contentTag.innerText = '內容2';
          break;
        case 'tab3':
          contentTag.innerText = '內容3';
          break;
      }
    }, false);
  </script>
</body>
</html>

預覽

五、實現下圖的模態框功能。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>fifth</title>
  <style>
    *{
      margin: 0px;
      padding: 0px;
    }
    a{
      text-decoration: none;
      color: black;
    }
    hr{
      border-color: #fff;
    }
    .clearFix:after{
      content: '';
      display: block;
      clear: both;
    }
    .cover{
      background: black;
      position: fixed;
      top: 0;
      left: 0;
      opacity: 0.3;
      width: 100vw;
        height: 100vh;
      display: none;
    }
    .modal{
      position: absolute;
      top: 50%;
      left: 50%;
      width: 400px;
      transform: translate(-50%, -50%);  //絕對定位+transform, 只需設置寬度,高度自適應
      z-index: 1;
      border-radius: 4px;
      font-size: 18px;
      padding: 0 3px;
      background: #fff;
      display: none;
    }
    .header{
      height: 40px;
      line-height: 40px;
    }
    .header>h3{
      float: left;
    }
    .close{
      float: right;
    }
    .content{
      margin: 10px 0px;
      line-height: 36px;
    }
    .footer{
      float: right;
      height: 40px;
      line-height: 40px;
    }
    .footer>a{

    }
  </style>
</head>
<body>
  <button class='showModal'>點我1</button>
  <div class='cover'></div>
  <div class='modal'>
    <div class='header clearFix'>
      <h3>我是標題1</h3>
      <a class='close' href='#'>×</a>
    </div>
    <hr>
    <div class='content'>
      <p>我是內容1</p>
      <p>我是內容1</p>
    </div>
    <hr>
    <div class='footer clearFix'>
      <a class='cancel' href='#'>取消</a>
      <a class='confirm' href='#'>確定</a>
    </div>
  </div>

  <script>
    var btn = document.querySelector('.showModal'),
        modal = document.querySelector('.modal'),
        cover = document.querySelector('.cover'),
        close = document.querySelector('.close'),
        cancel = document.querySelector('.cancel');
    function showModal() {
      modal.style.display = 'block';
      cover.style.display = 'block';
    }
    function cancelModal() {
      modal.style.display = 'none';
      cover.style.display = 'none';
    }
    btn.addEventListener('click', function(e){
      showModal();
    }, false);
    cover.addEventListener('click', function(e){
      cancelModal();
    }, false);
    close.addEventListener('click', function(e){
      cancelModal();
    }, false);
    cancel.addEventListener('click', function(e){
      cancelModal();
    }, false);
  </script>
</body>
</html>

預覽

由于預覽好像有問題就放在js bin上面了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.dom對象的innerText和innerHTML有什么區別? innerText是一個可寫屬性,返回元素內包...
    GarenWang閱讀 466評論 0 0
  • 1.dom對象的innerText和innerHTML有什么區別? innerText是一個可寫屬性。將寫入的內容...
    candy252324閱讀 558評論 0 0
  • DOM0 事件和DOM2級在事件監聽使用方式上有什么區別? DOM 0 級事件是基于元素內聯屬性或DOM元素命名的...
    邢烽朔閱讀 349評論 0 0
  • 2017.10.31。無為。焦點解決分享第87天.。人這一輩子,活得不容易,要想與眾不同,就要含辛茹苦,就要忍辱負...
    無為wyw閱讀 135評論 1 2
  • 車窗外兩邊的樹飛快往后去了,天陰沉沉的,微微有點暈車的我聽著音樂瞌睡死了,前途未卜獨思量。旁邊的大爺時而打盹,時而...
    a1f3fb911c82閱讀 289評論 0 0