之前在這篇文章 基於.NetCore開發部落格專案 StarBlog - (8) 分類層級結構展示 中說到,我為了讓文章分類列表支援層級結構,用了一個樹形元件,不過這個元件太老了,使用的Bootstrap版本居然是3.x的,但又找不到更好的,只能硬著頭皮用。
但實際效果有很多我不滿意的,感謝開源,我直接fork一份程式碼來魔改,實現了我要的效果~
然後還上傳了npm~(第一次在npm上發包)
有需要的同學可以install試試:
npm i bootstrap5-treeview
先放圖,後面再來說改了啥
我注意到原版對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上發包,(也算是為開源社群做貢獻了)
參考了這篇文章: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
有需要實現樹形結構的同學可以試試,感覺還行~