魔改了一下bootstrap-treeview元件,釋出個NPM包體驗一下

程式設計實驗室發表於2022-05-27

前言

之前在這篇文章 基於.NetCore開發部落格專案 StarBlog - (8) 分類層級結構展示 中說到,我為了讓文章分類列表支援層級結構,用了一個樹形元件,不過這個元件太老了,使用的Bootstrap版本居然是3.x的,但又找不到更好的,只能硬著頭皮用。

但實際效果有很多我不滿意的,感謝開源,我直接fork一份程式碼來魔改,實現了我要的效果~

然後還上傳了npm~(第一次在npm上發包)

有需要的同學可以install試試:

npm i bootstrap5-treeview

效果

先放圖,後面再來說改了啥

image

佈局修改

我注意到原版對tag的處理是包裝成一個badge直接放在文字後面,不知道是不是Bootstrap改了,在目前的5.x版本上看起來擠在一起,而且也沒有顏色,因為原版作者只加了badge一個class

我直接在js程式碼裡找到這個badge的定義,修改!

Tree.prototype.template = {
    // ...
    badge: '<span class="ms-1 badge bg-primary rounded-pill"></span>'
};

加上了背景色和圓角,效果就好看多了~

然後!擠在一起的問題還沒解決,原本的實現渲染出來大概這樣的HTML

<ul class="list-group">
  <li class="list-group-item">An item</li>
  <li class="list-group-item">A second item</li>
  <li class="list-group-item">A third item</li>
  <li class="list-group-item">A fourth item</li>
  <li class="list-group-item">And a fifth one</li>
</ul>

理想情況下是兩邊分佈,用flex佈局正好實現,渲染出來應該類似這樣

<ol class="list-group">
  <li class="list-group-item d-flex justify-content-between align-items-start">
    <div>Subheading</div>
    <span class="badge bg-primary rounded-pill">tag</span>
  </li>
</ol>

但原本這個元件是把所有元素一個個append到list-group-item裡面,就導致出來的效果不美觀

沒事,程式碼在手,改!

首先重新定義幾個元素模板

包括上面的badge也在裡面,所有元素模板在這

Tree.prototype.template = {
    list: '<ul class="list-group"></ul>',
    itemWrapper: '<li class="list-group-item d-flex justify-content-between align-items-start"></li>',
    itemLeftElem: '<div class="w-100"></div>',
    itemRightElem: '<div></div>',
    indent: '<span class="mx-2"></span>',
    icon: '<span class="icon"></span>',
    link: '<a class="w-75" href="#" style="display:inline-block; color:inherit; text-decoration:none;"></a>',
    badge: '<span class="ms-1 badge bg-primary rounded-pill"></span>'
};

然後找到組裝列表元素項的程式碼

Tree.prototype.buildTree這裡,裡面有個$.each(nodes, function addNodes(id, node)迴圈體

直接改程式碼

// 最外層包裝
let treeItem = $(_this.template.itemWrapper)
.addClass('node-' + _this.elementId)
.addClass(node.state.checked ? 'node-checked' : '')
.addClass(node.state.disabled ? 'node-disabled' : '')
.addClass(node.state.selected ? 'node-selected' : '')
.addClass(node.searchResult ? 'search-result' : '')
.attr('data-nodeid', node.nodeId)
.attr('style', _this.buildStyleOverride(node));

// item 內分成兩個元素,用flex佈局分佈在左右兩邊
let treeItemLeft = $(_this.template.itemLeftElem)
let treeItemRight = $(_this.template.itemRightElem)
treeItem.append(treeItemLeft)
treeItem.append(treeItemRight)

然後把tag渲染程式碼改成這樣

// Add tags as badges
if (_this.options.showTags && node.tags) {
    $.each(node.tags, function addTag(id, tag) {
        treeItemRight.append(
            $(_this.template.badge).append(tag)
        );
    });
}

其他元素全都append到treeItemLeft元素下

增加縮排控制

原版沒辦法控制是否開啟子選單縮排,預設是開啟,我給加了個選項控制開啟

_default.settings = {
    // ...
    enableIndent: true, // 新增了控制是否啟用縮排的開關
}

然後依然是在上面的那個$.each(nodes, function addNodes(id, node)迴圈裡,加個判斷就搞定了

// Add indent/spacer to mimic tree structure
// 新增了控制是否啟用縮排的開關
if (_this.options.enableIndent) {
    for (let i = 0; i < (level - 1); i++) {
        treeItemLeft.append(_this.template.indent);
    }
}

上傳NPM

第一次在NPM上發包,(也算是為開源社群做貢獻了)

參考了這篇文章:https://segmentfault.com/a/1190000013940567

首先在NPM官網註冊一個賬號,然後本地使用npm login登入

完事了在專案的根目錄下執行:npm publish就好了

當然我這個是fork的,要把package.json裡的資訊改一下,不然會和原作者的包衝突沒法上傳。

小結

魔改前端元件和在NPM發包這的門檻真的是很低,讓我想起了之前在pip上發python包的經歷,也是類似的操作,一鍵提交,直接起飛~

不過相比之下,NPM甚至比pip還更容易一點,至少沒遇到什麼障礙,也不需要額外安裝什麼就完成了

(唯一的障礙是這個包的依賴太老,grunt的上古版本我安不上,後面裝了新版才可以執行任務)

程式碼

完整程式碼在github:https://github.com/Deali-Axy/bootstrap5-treeview

然後NPM地址:https://www.npmjs.com/package/bootstrap5-treeview

有需要實現樹形結構的同學可以試試,感覺還行~

相關文章