No.26 DOM

一涩馆、DOM簡介

文檔對象模型(Document Object Model罐栈,簡稱 DOM)优床,是 W3C 組織推薦的處理可擴展標記語言(HTML或者XML)的標準編程接口。
W3C 已經(jīng)定義了一系列的 DOM 接口丁鹉,通過這些 DOM 接口可以改變網(wǎng)頁的內(nèi)容、結構和樣式悴能。


DOM 樹
  • 文檔:一個頁面就是一個文檔揣钦,DOM 中使用 document 表示
  • 元素:頁面中的所有標簽都是元素,DOM 中使用 element 表示
  • 節(jié)點:網(wǎng)頁中的所有內(nèi)容都是節(jié)點(標簽漠酿、屬性冯凹、文本、注釋等)炒嘲,DOM 中使用 node 表示
    DOM 把以上內(nèi)容都看做是對象宇姚。

二、獲取元素

1. 根據(jù) ID 獲取

使用 getElementById() 方法可以獲取帶有 ID 的元素對象夫凸。
document.getElementById('id');

2. 根據(jù)標簽名獲取

使用 getElementsByTagName() 方法可以返回帶有指定標簽名的對象的集合浑劳。
document.getElementsByTagName('標簽名');
注意:
因為得到的是一個對象的集合,所以我們想要操作里面的元素就需要遍歷夭拌。
得到元素對象是動態(tài)的
如果獲取不到元素,則返回為空的偽數(shù)組(因為獲取不到對象)

還可以獲取某個元素(父元素)內(nèi)部所有指定標簽名的子元素.
element.getElementsByTagName('標簽名');
注意:父元素必須是單個對象(必須指明是哪一個元素對象). 獲取的時候不包括父元素自己魔熏。

3. 通過 HTML5 新增的方法獲取

根據(jù)類名返回元素對象集合
document.getElementsByClassName('類名');

根據(jù)指定選擇器返回第一個元素對象
document.querySelector('選擇器');

根據(jù)指定選擇器返回
document.querySelectorAll('選擇器');

注意:
querySelector 和 querySelectorAll里面的選擇器需要加符號,
比如:document.querySelector('#nav');

4. 獲取特殊元素(body,html)

返回body元素對象
doucument.body

返回html元素對象
document.documentElement

三啼止、操作元素

1. 改變元素內(nèi)容

element.innerText
從起始位置到終止位置的內(nèi)容, 但它去除 html 標簽道逗, 同時空格和換行也會去掉

element.innerHTML
起始位置到終止位置的全部內(nèi)容,包括 html 標簽献烦,同時保留空格和換行

2. 常用元素的屬性操作

  1. innerText滓窍、innerHTML 改變元素內(nèi)容
  2. src、href
  3. id巩那、alt吏夯、title

3. 表單元素的屬性操作

利用 DOM 可以操作如下表單元素的屬性:
type、value即横、checked噪生、selected、disabled

4. 樣式屬性操作

我們可以通過 JS 修改元素的大小东囚、顏色跺嗽、位置等樣式。

  1. element.style 行內(nèi)樣式操作
  2. element.className 類名樣式操作

注意:

  1. JS 里面的樣式采取駝峰命名法 比如 fontSize、 backgroundColor
  2. JS 修改 style 樣式操作桨嫁,產(chǎn)生的是行內(nèi)樣式植兰,CSS 權重比較高
  3. 如果樣式修改較多,可以采取操作類名方式更改元素樣式
  4. class因為是個保留字璃吧,因此使用className來操作元素類名屬性
  5. className 會直接更改元素的類名楣导,會覆蓋原先的類名

5. classList 屬性

classList屬性是HTML5新增的一個屬性,返回元素的類名畜挨。但是ie10以上版本支持筒繁。
該屬性用于在元素中添加,移除及切換 CSS 類巴元。

添加類:
element.classList.add(’類名’);
focus.classList.add(‘current’);

移除類:
element.classList.remove(’類名’);
focus.classList.remove(‘current’);

切換類:
element.classList.toggle(’類名’);
focus.classList.toggle(‘current’);

注意以上方法里面毡咏,所有類名都不帶點

6. 排他思想

排他思想

如果有同一組元素,我們想要某一個元素實現(xiàn)某種樣式务冕, 需要用到循環(huán)的排他思想算法:

  1. 所有元素全部清除樣式(干掉其他人)
  2. 給當前元素設置樣式 (留下我自己)
  3. 注意順序不能顛倒血当,首先干掉其他人,再設置自己

7. 自定義屬性的操作

  1. 獲取屬性值
    element.屬性 獲取屬性值禀忆。
    element.getAttribute('屬性');
    區(qū)別:
    element.屬性 獲取內(nèi)置屬性值(元素本身自帶的屬性)
    element.getAttribute(‘屬性’); 主要獲得自定義的屬性 (標準) 我們程序員自定義的屬性
  2. 設置屬性值
    element.屬性 = ‘值’ 設置內(nèi)置屬性值臊旭。
    element.setAttribute('屬性', '值');
    區(qū)別:
    element.屬性 設置內(nèi)置屬性值
    element.setAttribute(‘屬性’); 主要設置自定義的屬性 (標準)
  3. 移除屬性
    element.removeAttribute('屬性');

8. H5自定義屬性

自定義屬性目的:是為了保存并使用數(shù)據(jù)。有些數(shù)據(jù)可以保存到頁面中而不用保存到數(shù)據(jù)庫中箩退。
自定義屬性獲取是通過getAttribute('屬性') 獲取离熏。
但是有些自定義屬性很容易引起歧義,不容易判斷是元素的內(nèi)置屬性還是自定義屬性戴涝。
H5給我們新增了自定義屬性:

  1. 設置H5自定義屬性
    H5規(guī)定自定義屬性data-開頭做為屬性名并且賦值滋戳。
    比如 <div data-index=“1”></div>
    或者使用 JS 設置
    element.setAttribute(‘data-index’, 2)
  2. 獲取H5自定義屬性
    兼容性獲取 element.getAttribute('data-index');
    H5新增 element.dataset.index 或者 element.dataset[‘index’] ie 11才開始支持

四、節(jié)點操作

1. 獲取元素通常使用兩種方式

  1. 利用 DOM 提供的方法獲取元素
    document.getElementById()
    document.getElementsByTagName()
    document.querySelector 等
    邏輯性不強啥刻、繁瑣
  2. 利用節(jié)點層級關系獲取元素
    利用父子兄節(jié)點關系獲取元素
    邏輯性強奸鸯, 但是兼容性稍差

2. 節(jié)點概述

網(wǎng)頁中的所有內(nèi)容都是節(jié)點(標簽、屬性可帽、文本娄涩、注釋等),在DOM 中映跟,節(jié)點使用 node 來表示蓄拣。
HTML DOM 樹中的所有節(jié)點均可通過 JavaScript 進行訪問,所有 HTML 元素(節(jié)點)均可被修改努隙,也可以創(chuàng)建或刪除球恤。

一般地,節(jié)點至少擁有nodeType(節(jié)點類型)荸镊、nodeName(節(jié)點名稱)和nodeValue(節(jié)點值)這三個基本屬性咽斧。

元素節(jié)點 nodeType 為 1
屬性節(jié)點 nodeType 為 2
文本節(jié)點 nodeType 為 3 (文本節(jié)點包含文字堪置、空格、換行等)
注釋節(jié)點 nodeType 為 8
我們在實際開發(fā)中张惹,節(jié)點操作主要操作的是元素節(jié)點

3. 節(jié)點層級

利用 DOM 樹可以把節(jié)點劃分為不同的層級關系晋柱,常見的是父子兄層級關系。

  1. 父級節(jié)點

node.parentNode
parentNode 屬性可返回某節(jié)點的父節(jié)點诵叁,注意是最近的一個父節(jié)點
如果指定的節(jié)點沒有父節(jié)點則返回 null

  1. 子節(jié)點

parentNode.childNodes(標準)
parentNode.childNodes 返回包含指定節(jié)點的子節(jié)點的集合,該集合為即時更新的集合钦椭。
注意:返回值里面包含了所有的子節(jié)點拧额,包括元素節(jié)點,文本節(jié)點等彪腔。
如果只想要獲得里面的元素節(jié)點侥锦,則需要專門處理。 所以我們一般不提倡使用childNodes

var ul = document. querySelector('ul');
for(var i = 0; i < ul.childNodes.length;i++) {
    if (ul.childNodes[i].nodeType == 1) {    // ul.childNodes[i] 是元素節(jié)點
        console.log(ul.childNodes[i]);
    }
}



parentNode.children(非標準)
parentNode.children 是一個只讀屬性德挣,返回所有的子元素節(jié)點恭垦。它只返回子元素節(jié)點,其余節(jié)點不返回格嗅。
雖然children 是一個非標準番挺,但是得到了各個瀏覽器的支持,因此我們可以放心使用

parentNode.firstChild
firstChild 返回第一個子節(jié)點屯掖,找不到則返回null玄柏。同樣,也是包含所有的節(jié)點贴铜。包括元素節(jié)點粪摘,文本節(jié)點等。
parentNode.lastChild
lastChild 返回最后一個子節(jié)點绍坝,找不到則返回null徘意。同樣,也是包含所有的節(jié)點轩褐。包括元素節(jié)點椎咧,文本節(jié)點等。

parentNode.firstElementChild
firstElementChild 返回第一個子元素節(jié)點灾挨,找不到則返回null邑退。
parentNode.lastElementChild
lastElementChild 返回最后一個子元素節(jié)點,找不到則返回null劳澄。
注意:這兩個方法有兼容性問題地技,IE9 以上才支持。

實際開發(fā)中秒拔,firstChild 和 lastChild 包含其他節(jié)點莫矗,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性問題,
那么我們?nèi)绾潍@取第一個子元素節(jié)點或最后一個子元素節(jié)點呢作谚?
解決方案:
如果想要第一個子元素節(jié)點三娩,可以使用 parentNode.chilren[0]
如果想要最后一個子元素節(jié)點,可以使用 parentNode.chilren[parentNode.chilren.length - 1]

  1. 兄弟節(jié)點

node.nextSibling
nextSibling 返回當前元素的下一個兄弟元素節(jié)點妹懒,找不到則返回null雀监。同樣,也是包含所有的節(jié)點眨唬。
node.previousSibling
previousSibling 返回當前元素上一個兄弟元素節(jié)點会前,找不到則返回null。同樣匾竿,也是包含所有的節(jié)點瓦宜。

node.nextElementSibling
nextElementSibling 返回當前元素下一個兄弟元素節(jié)點,找不到則返回null岭妖。
node.previousElementSibling
previousElementSibling 返回當前元素上一個兄弟節(jié)點临庇,找不到則返回null。
注意:這兩個方法有兼容性問題昵慌, IE9 以上才支持假夺。

自己封裝一個兼容性的函數(shù):

function getNextElementSibling(element) {
    var el = element;
    while (el = el.nextSibling) {
        if (el.nodeType === 1) {
            return el;
        }
    }
    return null;
}  

4. 節(jié)點創(chuàng)建

document.createElement('tagName')
document.createElement() 方法創(chuàng)建由 tagName 指定的 HTML 元素。因為這些元素原先不存在斋攀,是根據(jù)我們的需求動態(tài)生成的侄泽,所以我們也稱為動態(tài)創(chuàng)建元素節(jié)點。

5. 節(jié)點添加

node.appendChild(child)
node.appendChild() 方法將一個節(jié)點添加到指定父節(jié)點的子節(jié)點列表末尾蜻韭。類似于 CSS 里面的 after 偽元素悼尾。
node.insertBefore(child, 指定元素)
node.insertBefore() 方法將一個節(jié)點添加到父節(jié)點的指定子節(jié)點前面。類似于 CSS 里面的 before 偽元素肖方。

6. 節(jié)點刪除

node.removeChild(child)
node.removeChild() 方法從 DOM 中刪除一個子節(jié)點闺魏,返回刪除的節(jié)點。

阻止鏈接跳轉需要添加 javascript:void(0); 或者 javascript:;
<a href='javascript:;'>刪除</a>

俯画?析桥??什么都不寫也可以啊艰垂,留一個疑問泡仗??猜憎?


2020年2月1日疑問解除:
如果什么都不寫娩怎,a標簽作為一個按鈕進行事件響應時,可能不會響應完全胰柑,切割輪播圖的坑截亦。

<a href="javascript:;" class="next">&gt;</a>
<script src="js/jquery.min.js"></script>
<script>
    $(function () {
        var index = 0;
        var flag = true;
        $(".next").on("click", function () {
            if (flag == true) {
                flag = false;
                index--;
                $("li").each(function (key) {
                    $(this).css({
                        "transform": "rotateX(" + (index * 90) + "deg)",
                        "transition-delay": (key * 0.2) + "s"
                    });
                });
                setTimeout(function () {
                    flag = true;
                }, 1000);
            }
        });
    });
</script>

完整代碼見代碼附錄爬泥。

7. 節(jié)點復制(節(jié)點克隆)

node.cloneNode()
node.cloneNode() 方法返回調(diào)用該方法的節(jié)點的一個副本崩瓤。 也稱為克隆節(jié)點/拷貝節(jié)點

注意:

  1. 如果括號參數(shù)為空或者為 false 袍啡,則是淺拷貝,即只克隆復制節(jié)點本身却桶,不克隆里面的子節(jié)點境输。
  2. 如果括號參數(shù)為 true ,則是深度拷貝颖系,會復制節(jié)點本身以及里面所有的子節(jié)點畴嘶。

8. 三種動態(tài)創(chuàng)建元素區(qū)別

document.write()
element.innerHTML
document.createElement()

區(qū)別:

  1. document.write 是直接將內(nèi)容寫入頁面的內(nèi)容流,但是文檔流執(zhí)行完畢集晚,則它會導致頁面全部重繪
  2. innerHTML 是將內(nèi)容寫入某個 DOM 節(jié)點,不會導致頁面全部重繪
  3. innerHTML 創(chuàng)建多個元素效率更高(不要拼接字符串区匣,采取數(shù)組形式拼接)偷拔,結構稍微復雜
  4. createElement() 創(chuàng)建多個元素效率稍低一點點,但是結構更清晰
    總結:不同瀏覽器下亏钩,innerHTML 效率要比 creatElement 高

五莲绰、DOM 總結

關于dom操作,主要針對于元素對象的操作姑丑。
主要有創(chuàng)建蛤签、增、刪栅哀、改震肮、查、屬性操作留拾。

1. 創(chuàng)建

  • document.write
  • innerHTML
  • createElement

2. 增

  • appendChild
  • insertBefore

3. 刪

  • removeChild

4. 改

主要修改dom的元素屬性戳晌,dom元素的內(nèi)容、屬性, 表單的值等

  • 修改元素屬性: src痴柔、href沦偎、title等
  • 修改普通元素內(nèi)容: innerHTML 、innerText
  • 修改表單元素: value咳蔚、type豪嚎、disabled等
  • 修改元素樣式: style、className

5. 查

主要獲取查詢dom的元素

  • DOM提供的API 方法: getElementById谈火、getElementsByTagName 古老用法 不太推薦
  • H5提供的新方法: querySelector侈询、querySelectorAll 提倡
  • 利用節(jié)點操作獲取元素: 父(parentNode)、子(children)糯耍、兄(previousElementSibling妄荔、nextElementSibling) 提倡

6. 屬性操作

主要針對于自定義屬性

  • setAttribute:設置dom的屬性值
  • getAttribute:得到dom的屬性值
  • removeAttribute移除屬性

代碼附錄

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>切割輪播圖</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        body {
            background-color: #000000;
        }

        .view {
            width: 560px;
            height: 300px;
            margin: 100px auto;
            position: relative;

        }

        ul {
            width: 100%;
            height: 100%;
            list-style: none;
            transform: rotate3d(0, 0, 0, 0deg);

            transform-style: preserve-3d;
        }

        ul > li {
            width: 20%;
            height: 100%;
            float: left;
            position: relative;
            transform-style: preserve-3d;
            transition: transform 0.5s;
        }

        ul > li > span {
            width: 100%;
            height: 100%;
            position: absolute;
            left: 0;
            top: 0;
        }

        ul > li > span:nth-of-type(1) {
            background: url("images/q1.jpg");
            transform: translateZ(150px);
        }

        ul > li > span:nth-of-type(2) {
            background: url("images/q2.jpg");
            transform: translateY(-150px) rotateX(90deg);
        }

        ul > li > span:nth-of-type(3) {
            background: url("images/q3.jpg");
            transform: translateZ(-150px) rotateX(180deg);
        }

        ul > li > span:nth-of-type(4) {
            background: url("images/q4.jpg");
            transform: translateY(150px) rotateX(-90deg);
        }

        ul > li:nth-of-type(2) > span {
            background-position: -100% 0;
        }

        ul > li:nth-of-type(3) > span {
            background-position: -200% 0;
        }

        ul > li:nth-of-type(4) > span {
            background-position: -300% 0;
        }

        ul > li:nth-of-type(5) > span {
            background-position: -400% 0;
        }

        .pre, .next {
            width: 60px;
            height: 60px;
            text-align: center;
            line-height: 60px;
            position: absolute;
            top: 50%;
            text-decoration: none;
            font-size: 40px;
            transform: translate(0, -50%);
            background-color: rgba(0, 0, 0, 0.5);
            color: white;
        }

        .pre {
            left: 0;
        }

        .next {
            right: 0;
        }
    </style>
</head>
<body>
<div class="view">

    <ul>
        <li>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </li>
        <li>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </li>
        <li>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </li>
        <li>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </li>
        <li>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </li>
    </ul>

    <a href="javascript:;" class="pre">&lt;</a>
    <a href="javascript:;" class="next">&gt;</a>
</div>
<script src="js/jquery.min.js"></script>
<script>
    $(function () {
        var index = 0;
        var flag = true;
        $(".next").on("click", function () {
            if (flag == true) {
                flag = false;
                index--;
                $("li").each(function (key) {
                    $(this).css({
                        "transform": "rotateX(" + (index * 90) + "deg)",
                        "transition-delay": (key * 0.2) + "s"
                    });

                });
                setTimeout(function () {
                    flag = true;
                }, 1000);
            }

        });

        $(".pre").on("click", function () {
            if (flag == true) {
                flag = false;
                index++;
                $("li").each(function (key) {
                    $(this).css({
                        "transform": "rotateX(" + index * 90 + "deg",
                        "transition-delay": key * 0.2 + "s"
                    });

                });
                setTimeout(function () {
                    flag = true;
                }, 1000);
            }

        });

    });
</script>
</body>
</html>
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泼菌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子啦租,更是在濱河造成了極大的恐慌哗伯,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篷角,死亡現(xiàn)場離奇詭異焊刹,居然都是意外死亡,警方通過查閱死者的電腦和手機恳蹲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門虐块,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嘉蕾,你說我怎么就攤上這事贺奠。” “怎么了错忱?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵儡率,是天一觀的道長。 經(jīng)常有香客問我以清,道長儿普,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任掷倔,我火速辦了婚禮眉孩,結果婚禮上,老公的妹妹穿的比我還像新娘勒葱。我一直安慰自己浪汪,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布凛虽。 她就那樣靜靜地躺著吟宦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涩维。 梳的紋絲不亂的頭發(fā)上殃姓,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機與錄音瓦阐,去河邊找鬼蜗侈。 笑死,一個胖子當著我的面吹牛睡蟋,可吹牛的內(nèi)容都是我干的踏幻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼戳杀,長吁一口氣:“原來是場噩夢啊……” “哼该面!你這毒婦竟也來了夭苗?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤隔缀,失蹤者是張志新(化名)和其女友劉穎题造,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猾瘸,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡界赔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了牵触。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淮悼。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖揽思,靈堂內(nèi)的尸體忽然破棺而出袜腥,到底是詐尸還是另有隱情,我是刑警寧澤钉汗,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布羹令,位于F島的核電站,受9級特大地震影響儡湾,放射性物質發(fā)生泄漏。R本人自食惡果不足惜执俩,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一徐钠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧役首,春花似錦尝丐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至矮固,卻和暖如春失息,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背档址。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工盹兢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人守伸。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓绎秒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尼摹。 傳聞我的和親對象是個殘疾皇子见芹,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355