成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript生成TOC

chinafgj / 2234人閱讀

摘要:本人為菜鳥,有問題請(qǐng)指正目錄最近用搭建個(gè)人博客在制作文章顯示頁面時(shí),需要在前端頁面生成。剛開始很糾結(jié)如何生成有層級(jí)結(jié)構(gòu)的代碼,最后發(fā)現(xiàn)可以使用設(shè)計(jì)模式中的組合模式來完成這一功能。具體點(diǎn)就是將節(jié)點(diǎn)看作葉子節(jié)點(diǎn),節(jié)點(diǎn)看錯(cuò)作容器。

本人為Javascript菜鳥,有問題請(qǐng)指正...

TOC目錄

最近用Flask搭建個(gè)人博客在制作文章顯示頁面時(shí),需要在前端頁面生成TOC。就打算自己寫一個(gè)JavaScript腳本。

需要生成的目標(biāo)HTML代碼如下:

    

在看了JavaScript權(quán)威指南這本書后,發(fā)現(xiàn)其中雖然有例子生成TOC,但是并沒有顯示層級(jí)。不過,其中有一個(gè)記錄TOC各個(gè)錨點(diǎn)序號(hào)的好方法:

# 使用一個(gè)數(shù)組報(bào)錯(cuò)的level為1
var level = parseInt(header.tagName.charAt(1));
# 當(dāng)處理一個(gè)標(biāo)簽后,計(jì)算加1
sectionNumbers[level-1]++
# 然后去當(dāng)前序號(hào) 比如序號(hào)為2.1.1
sectionNumber = sectionNumbers.slice(0,level).join(".")
分析算法邏輯

吹牛B之前需要打草稿,寫代碼之前也如此。

剛開始很糾結(jié)如何生成有層級(jí)結(jié)構(gòu)的HTML代碼,最后發(fā)現(xiàn)可以使用設(shè)計(jì)模式中的組合模式來完成這一功能。具體點(diǎn)就是將li節(jié)點(diǎn)看作葉子節(jié)點(diǎn),ul節(jié)點(diǎn)看錯(cuò)作容器。那么就有一下限制:

只有ul節(jié)點(diǎn)可以插入li節(jié)點(diǎn)

li節(jié)點(diǎn)需要插入子節(jié)點(diǎn),就需要?jiǎng)?chuàng)建一個(gè)ul子節(jié)點(diǎn),讓子節(jié)點(diǎn)去插入li節(jié)點(diǎn)

ul與它的li子節(jié)點(diǎn)level相同

如果當(dāng)前節(jié)點(diǎn)需要處理一個(gè)header,就需要作出以下判斷:

判斷自己為ul節(jié)點(diǎn)還是li節(jié)點(diǎn)

如果為ul節(jié)點(diǎn),且待處理的header的level與自己相同,那么就直接生成一個(gè)li節(jié)點(diǎn)并插入;如果待處理的header的level比自己大,那么就找到子節(jié)點(diǎn),交給子節(jié)點(diǎn)去處理。

如果為li節(jié)點(diǎn),且待處理的header的level比自己大,那么就取li節(jié)點(diǎn)的ul節(jié)點(diǎn),交給ul節(jié)點(diǎn)去處理

一直向下去處理header,直到插入成功

代碼實(shí)現(xiàn)

為了盡量減少代碼的污染,使用Fucntion.call(args)方式了動(dòng)態(tài)的給節(jié)點(diǎn)添加屬性:

var sectionNumbers = [0, 0, 0, 0, 0, 0];

function Toc() {
    this.headers = $(this).find(":header");
    var ul = document.createElement("ul");
    this.toc = TocObj.call(ul, 1);
    for(var i = 0; i < this.headers.length; i++) {
        // if(i > 1) break;
        this.toc.add(this.headers[i]);
    }
    console.log(this.toc);
}

function TocObj(level) {
    this.level = level;
    this.num = 0;
    this.add = function(header) {
        var flag = this.tagName == "UL"; // ul節(jié)點(diǎn)和li節(jié)點(diǎn)處理header的方式不通過
        var level = parseInt(header.tagName.charAt(1));
        if(flag) { // 只有ul節(jié)點(diǎn)才能插入li
            if(this.num == 0 || level == this.level) {
                var link = document.createElement("a");
                link.href = "";
                link.innerHTML = header.innerHTML;
                sectionNumbers[level-1]++;
                for(var i = level; i < sectionNumbers.length; i++) sectionNumbers[i] = 0;
                link.href = "#TOC" + sectionNumbers.slice(0, level).join(".");
                var li = document.createElement("li");
                li.insertBefore(link, li.firstChild);
                this.num++;
                this.appendChild(TocObj.call(li, level));
            } else if(level > this.level){
                if(this.num == 0) { 
                    throw new Error("level error 1");  
                }
                var lastChild = this.lastChild;
                lastChild.add(header); // 讓ul節(jié)點(diǎn)的li節(jié)點(diǎn)去處理header
            }
        } else { // li節(jié)點(diǎn)讓它的ul子節(jié)點(diǎn)去插入li
            if(level == this.level) {
                throw new Error("level error 2");
            } else if(level > this.level){ 
                if(this.num == 0) { // 沒有ul子節(jié)點(diǎn),就創(chuàng)建一個(gè)
                    var ul = document.createElement("ul");
                    this.appendChild(ul);
                    this.num++;
                    TocObj.call(ul, level).add(header); // 注意設(shè)置level
                } else { 
                    var lastChild = this.lastChild;
                    lastChild.add(header); //讓ul節(jié)點(diǎn)去處理這個(gè)header
                }
            }
        }
    }
    return this;
}

var toc = document.getElementsByClassName("post")[0];
Toc.call(toc);
效果展示

對(duì)于有以下結(jié)構(gòu)的HTML代碼:

標(biāo)題1

標(biāo)題1.1

標(biāo)題1.2

標(biāo)題2

標(biāo)題2.1

標(biāo)題2.1.1

標(biāo)題3

標(biāo)題4

標(biāo)題5

輸出結(jié)構(gòu)如下:

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/87713.html

相關(guān)文章

  • 為你的文章生成目錄索引

    摘要:使用可以快速為你的頁面生成目錄的結(jié)構(gòu),擁有較強(qiáng)的可定制性,并且并不會(huì)擅自為你做太多的事情,以便你更容易地把應(yīng)用到你的項(xiàng)目中。 引言 為頁面中的標(biāo)題元素建立目錄索引,這是一個(gè)不起眼卻很實(shí)用的功能,特別是對(duì)于那些含有篇幅很長的文章的頁面,擁有一個(gè)目錄可以讓讀者對(duì)文章的結(jié)構(gòu)一目了然,更重要的是,讀者可以很輕松地在文章的各個(gè)章節(jié)之間來回快速跳轉(zhuǎn),極大地提高了用戶體驗(yàn)。 toc.js 使用 to...

    魏憲會(huì) 評(píng)論0 收藏0
  • JavaScript Style Guide

    摘要:在作用域頂部聲明變量,避免變量聲明和賦值引起的相關(guān)問題。分號(hào)語句結(jié)束一定要加分號(hào)類型轉(zhuǎn)換在語句的開始執(zhí)行類型轉(zhuǎn)換字符串對(duì)數(shù)字使用并且總是帶上類型轉(zhuǎn)換的基數(shù)布爾值命名約定避免單個(gè)字符名,讓你的變量名有描述意義。 原文:https://github.com/airbnb/javascript JavaScript規(guī)范 內(nèi)容列表 類型 對(duì)象 數(shù)組 字符串 函數(shù) 屬性 變量 條件表達(dá)式和等號(hào)...

    habren 評(píng)論0 收藏0
  • 導(dǎo)出 VuePress 構(gòu)建的網(wǎng)站為 PDF

    摘要:文章首發(fā)自我的個(gè)人網(wǎng)站前言學(xué)也有一段時(shí)間了網(wǎng)上也有不少官方文檔的中文翻譯版但是似乎只有中文網(wǎng)站文檔一直是最新的奈何并沒有供直接下載是在是不太方便為了方便閱讀以及方便后續(xù)文檔更新決定用寫一個(gè)爬蟲將網(wǎng)頁下載下來保持為最后完成結(jié)果如下是的沒錯(cuò) 文章首發(fā)自我的 個(gè)人網(wǎng)站-Leetaos Blog 前言 學(xué) Rust 也有一段時(shí)間了,網(wǎng)上也有不少官方文檔的中文翻譯版,但是似乎只有 [Rust中...

    AlphaWallet 評(píng)論0 收藏0
  • cheerio制作markDown索引目錄

    摘要:原文鏈接的博客制作目錄索引這種東西當(dāng)然是放在前端方便。選擇放在后端一是為了了解后端生態(tài),掌握更多后端技術(shù)二是因?yàn)楣緦?shí)行前后端分離的方式開發(fā),睪貴的后端經(jīng)常啥也不做處理就返回一個(gè)數(shù)據(jù)甚至有時(shí)時(shí)間戳都不處理,對(duì)此有些無語。 原文鏈接:Bougie的博客 制作目錄索引這種東西當(dāng)然是放在前端方便。選擇放在后端一是為了了解Node后端生態(tài),掌握更多后端技術(shù);二是因?yàn)楣緦?shí)行前后端分離的方式開發(fā)...

    wanglu1209 評(píng)論0 收藏0
  • 為 github markdown 文件生成目錄

    摘要:文件一鍵生成目錄支持優(yōu)雅的寫法支持多次生成支持重復(fù)標(biāo)題的生成支持特殊字符的過濾支持指定不同的文件編碼支持文件夾的文件批量處理可指定是否包含子文件夾文件支持是否寫入文件,可返回目錄的內(nèi)容,便于用戶自行處理環(huán)境依賴請(qǐng)確保設(shè)置正確。 業(yè)務(wù)需要 在編寫 github 項(xiàng)目時(shí),有時(shí)候會(huì)編寫各種 README.md 等 markdown 文件,但是 github 默認(rèn)是沒有目錄的。 于是就自己想辦...

    Mr_houzi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<