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 许可协议。转载请注明出处!
相关文章
主流 nodejs 包管理器 pnpm vs bun vs npm vs yarn 简单横评
pnpm还真是会玩空间魔术?单项目里它领先优势就这么点?Node.js 20把npm喂肥了,现在谁还敢说npm是废物?这测试结果真是让人摸不着头脑。
2025-08-27 · Web前端 · 约 1 分钟
代码使我头疼之React初学习
前言 开始了,去年(2020)说要学的React,到现在2021年的12月底了,才来实施……(年底警告!~~年末总结还没开始写!~~) 不过前端为啥要学React呢?Vue不是很好用吗?Vue确实很好用,并且MVVM模式也更容易让人接受和理解,但大概是各种社区上都说react yyds啦,react一统江山啦什么的,加上我之前学Flutter做了很多项目,对声明式UI的思想已经基本掌握了,所以就想
2021-12-26 · Web前端 · 约 1 分钟
Next.js路由段配置选项笔记
Next.js的路由段配置选项?真有这么简单?官方文档写得倒是分散,自己整理下倒也罢了。动态渲染还是静态?缓存策略又该怎么定?开发者还是得自己琢磨。
2025-10-30 · Web前端 · 约 1 分钟
视频中台解决方案:组织树组件+多路视频直播界面开发
这种国产粗犷风格的项目居然能用?16路视频播放界面倒是简单直接,但现场配置和设备管理流程真是够折腾的。WVP和mpegts.js?B站开源的尿性,细节全靠蒙。
2025-07-04 · Web前端 · 约 1 分钟
讨论
共 0 条加载评论中…