formatter是添加操作按钮的核心入口,通过columns中配置列并返回html字符串实现;接收value、row、index参数,需用事件委托绑定点击行为,禁用内联onclick,避免xss与性能问题。

bootstrap-table 的 formatter 是添加操作按钮的核心入口
直接在 columns 配置里加一列,用 formatter 返回按钮 HTML 字符串,这是最常用也最可控的方式。它不依赖服务端返回按钮字段,也不需要额外 DOM 操作,渲染时机由表格自身控制。
常见错误是把按钮写成静态字符串(比如 "<button>编辑</button>"),结果点击没反应——因为事件没绑定;或者用 onclick="editRow(...)" 写内联 JS,但函数未定义或作用域不对。
-
formatter函数接收三个参数:value(当前单元格值)、row(整行数据)、index(行索引),必须靠row.id或类似主键字段定位目标记录 - 按钮 class 最好带唯一标识,比如
class="btn-edit" data-id="'+row.id+'",后续用事件委托绑定更安全 - 避免在
formatter里直接调用$.ajax或复杂逻辑,会拖慢表格渲染速度
用事件委托绑定按钮点击比内联 onclick 更可靠
表格重绘(如分页、刷新、搜索)后,内联 onclick 绑定的函数容易失效或重复绑定;而用 $(document).on('click', '.btn-delete', ...) 可以一次注册、长期有效。
典型场景:用户点“删除”,弹确认框,再发请求;点“详情”,打开 Modal 并填充 row 数据。这些动作都该在事件回调里做,而不是塞进 formatter。
- 不要在
formatter中写onclick="deleteItem('+row.id+')",数字 ID 拼接易出错,字符串字段含引号会直接 break JS - 推荐写法:
return '<button type="button" class="btn btn-sm btn-danger btn-delete" data-id="' + row.id + '">删除</button>'; - 事件绑定示例:
$(document).on('click', '.btn-delete', function() { const id = $(this).data('id'); confirmAndDelete(id); });
toolbar 配置适合批量操作,不是每行按钮的替代方案
toolbar 是表格上方的工具栏容器,用来放“新增”“批量删除”“导出”这类作用于全表或选中行的操作,和每行末尾的“编辑/查看”性质不同。混用会导致交互意图模糊。
比如用户点了某行的“编辑”按钮,又点了 toolbar 里的“编辑”,两者行为不一致(单行 vs 批量),UI 上也容易误点。
-
toolbar值是一个 CSS 选择器,如toolbar: '#toolbar',对应页面上一个<div id="toolbar"></div> - toolbar 按钮通常配合
$table.bootstrapTable('getSelections')获取选中行,不能直接拿到某一行上下文 - 如果真要实现“点某行再点 toolbar 编辑”,得自己维护选中状态(比如监听
check.bs.table事件),成本高于直接在行内放按钮
服务端渲染按钮字段 vs 前端 formatter:性能与灵活性权衡
有人让后端在 JSON 数据里直接返回 "action_html": "<button>..."</button> 字段,前端原样插入。这种方式省事,但隐患多:XSS 风险高、按钮样式难统一、无法动态禁用(比如“已归档”行禁用编辑)、调试困难。
相比之下,formatter 虽然多写几行 JS,但所有逻辑可控,按钮状态可基于 row.status 动态生成,还能结合权限字段做显隐控制。
- 服务端返回 HTML 字段时,务必对内容做严格转义,否则
row.name含"或<script></script>会破坏结构 - 前端生成按钮能轻松实现“编辑”变“保存中…”:先改按钮文字+禁用,请求完成后再还原,这种反馈体验服务端无法提供
- 小数据量(
真正容易被忽略的是按钮状态同步问题:比如点“删除”后,表格没刷新,但用户又去点同一行的“编辑”,这时候拿的还是旧数据。要么删完调 $table.bootstrapTable('refresh'),要么手动用 $table.bootstrapTable('removeByUniqueId', id) 删除本地行——后者快,但要注意是否启用了 sidePagination: 'server'。











