I modded the bootstrap-treeview component a bit and published an NPM package to try it out
Preface In a previous article, Building a Blog Project Based on .NetCore StarBlog - (8) Displaying Hierarchical Categories, I mentioned that to make the article category list support a hierarchical structure, I used a tree component. However, this component is too old—the Bootstrap version it uses is actually 3.x—but I couldn't find anything better, so I had to grit my teeth and use it. But I was unhappy with a lot of the actual results. The original author had simply given up and marked the project as Archived on GitHub. Nothing I could do. Thanks to open source, I just forked a copy of the code to
目录8 个章节
Preface
In a previous article Building a Blog Project Based on .NetCore StarBlog - (8) Displaying Hierarchical Categories, I mentioned that to make the article category list support a hierarchical structure, I used a tree component. However, this component is too old—the Bootstrap version it uses is actually 3.x—but I couldn't find anything better, so I had to grit my teeth and use it.
But I was unhappy with a lot of the actual results. The original author had simply given up and marked the project as Archived on GitHub. Nothing I could do.
Thanks to open source, I just forked a copy of the code and hacked it to get the effect I wanted~
Then I even uploaded it to npm~ (first time publishing a package on npm)
If you need it, you can try installing it:
npm i bootstrap5-treeview
The Result
I'll put the pictures first, then talk about what I changed

Layout Changes
I noticed that the original version wraps tags as a badge and puts them directly after the text. Not sure if it's because Bootstrap changed, but on the current 5.x version they look cramped together, and there's no color either, because the original author only added the badge class.
I went straight into the JS code, found the badge definition, and modified it!
Tree.prototype.template = {
// ...
badge: '<span class="ms-1 badge bg-primary rounded-pill"></span>'
};
Added a background color and rounded corners, and it looks much better~
Then! The cramped-together problem still wasn't solved. The original implementation rendered HTML roughly like this
<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>
Ideally they'd be distributed on both sides, which flex layout is perfect for. The rendered result should be something like this
<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>
But originally this component appended every element one by one into the list-group-item, which made the result look ugly
No problem, I've got the code, let's change it!
First, redefine a few element templates
Including the badge above, here are all the element templates
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>'
};
Then find the code that assembles the list item elements
In Tree.prototype.buildTree, there's a $.each(nodes, function addNodes(id, node) loop body
Just change the code
// 最外层包装
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)
Then change the tag rendering code to this
// 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 all other elements under the treeItemLeft element
Adding Indent Control
The original version had no way to control whether submenu indent is enabled; it was on by default. I added an option to control enabling it
_default.settings = {
// ...
enableIndent: true, // 添加了控制是否启用缩进的开关
}
Then still in that $.each(nodes, function addNodes(id, node) loop above, just add a condition and it's done
// Add indent/spacer to mimic tree structure
// 添加了控制是否启用缩进的开关
if (_this.options.enableIndent) {
for (let i = 0; i < (level - 1); i++) {
treeItemLeft.append(_this.template.indent);
}
}
Publishing to NPM
First time publishing a package on NPM, (I guess that counts as contributing to the open source community)
I referred to this article: https://segmentfault.com/a/1190000013940567
First register an account on the NPM website, then log in locally with npm login
Once that's done, run npm publish in the project root directory and you're good
Of course this is a fork, so I had to change the info in package.json, otherwise it would conflict with the original author's package and couldn't be uploaded.
Summary
The barrier to modding frontend components and publishing to NPM is really low. It reminded me of my previous experience publishing Python packages on pip—similar operations, one-click submit, and you're off~
But by comparison, NPM is even a bit easier than pip. At least I didn't run into any obstacles, and didn't need to install anything extra to get it done
(The only obstacle was that this package's dependencies are too old. I couldn't install the ancient version of grunt; later I installed a newer version and then I could run the tasks)
Code
Full code on GitHub: https://github.com/Deali-Axy/bootstrap5-treeview
And the NPM page: https://www.npmjs.com/package/bootstrap5-treeview
If you need to implement a tree structure, give it a try—I think it's pretty decent~
References
- Grunt Quick Start: https://www.gruntjs.net/getting-started
- How to publish your first npm package: https://segmentfault.com/a/1190000013940567
_EOF_
I modded the bootstrap-treeview component a bit and published an NPM package to try it out
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
NPM-Warn--ENOENT--no-such-file-or-directory
Now type the command to auto generate the package.json npm init --yes
2022-07-18 · Web前端 · 约 1 分钟
使用 swagger-typescript-api 在前端项目里生成请求代码
swagger-typescript-api?文档写得像草稿,还得自己摸索。那些花哨的模块化选项除了报错还能干嘛?老老实实生成单文件,配个客户端封装,省得每次折腾。
2025-11-03 · Web前端 · 约 1 分钟
主流 nodejs 包管理器 pnpm vs bun vs npm vs yarn 简单横评
pnpm还真是会玩空间魔术?单项目里它领先优势就这么点?Node.js 20把npm喂肥了,现在谁还敢说npm是废物?这测试结果真是让人摸不着头脑。
2025-08-27 · Web前端 · 约 1 分钟
2025年底的 TailwindCSS 组件库简单横评
TailwindCSS组件库多到让人选择困难。shadcn/ui虽优雅但不够全,Origin UI倒是堆了500+组件——这年头连UI都要内卷?大而全还是小而精,选型前先想清楚自己要不要加班调样式。
2025-11-23 · Web前端 · 约 1 分钟
讨论
共 0 条加载评论中…