作者 🐼
SpongeBob
-
表格搜索区域的搜索联动
-------------------------------
表格搜索联动或者事件监听需要通过layui.form来完成,例如监听下拉等事件可以使用如下:
const form = layui.form
//该notes变量是从view中声明的
const notes = notes
form.on("select", function(data) {
//data就是被监听的元素
//通过监听处理自己相关的业务逻辑,需要显示的时候要自己构建HTML然后操作DOM
//例如我选择一级分类后,再显示二级分类
let html = "<option value=''>- 全部 -</option>"
for (const key in notes.cate_sub) {
const item = notes.cate_sub[key]
if (item.pid == data.value) {
html += `<option value="${item.id}">${item.title}</option>`
}
}
//将HTML渲染到指定元素中
$('select[name="cate_sub"]').html(html)
})
//最后记得重新渲染表单中的select
form.render('select')
你提供的代码片段已经抓住了 Layui 实现搜索联动的核心逻辑。在实际表格搜索场景中,联动通常需要完成 **3个闭环**:监听变化 → 更新DOM → 触发表格查询。下面为你整理一套可直接复用的完整方案。
### 🔑 核心步骤
1. **精准监听**:使用 `form.on('select(lay-filter名)')` 代替全局监听,避免事件冲突。
2. **动态替换+重绘**:修改原生 `<select>` 的 `innerHTML` 后,**必须**调用 `form.render('select')`,否则 Layui 样式会错乱。
3. **联动查表**:根据需要决定是否在联动后自动刷新表格。
---
### 📦 完整示例(HTML + JS)
#### 1. 搜索区域 HTML
```html
<form class="layui-form" lay-filter="table-search">
<div class="layui-inline">
<label class="layui-form-label">一级分类</label>
<div class="layui-input-inline">
<select name="cate_pid" lay-filter="cate_pid">
<option value="">全部</option>
{volist name="top_cates" id="vo"}
<option value="{$vo.id}">{$vo.title}</option>
{/volist}
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">二级分类</label>
<div class="layui-input-inline">
<select name="cate_id" lay-filter="cate_id">
<option value="">全部</option>
</select>
</div>
</div>
<button type="submit" class="layui-btn" lay-submit lay-filter="search-btn">搜索</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</form>
<!-- 表格容器 -->
<table id="dataTable" lay-filter="dataTable"></table>
```
#### 2. JS 联动逻辑
```javascript
const $ = layui.$;
const form = layui.form;
const table = layui.table;
// 假设这是从 View 注入的全局数据(实际项目中建议改为接口请求)
const cateSubData = notes.cate_sub || [];
// ✅ 监听一级分类变化
form.on('select(cate_pid)', function(data) {
const pid = data.value;
let html = '<option value="">全部</option>';
// 筛选对应的二级分类
cateSubData.forEach(item => {
if (item.pid == pid) {
html += `<option value="${item.id}">${item.title}</option>`;
}
});
// 动态写入 DOM
$('select[name="cate_id"]').html(html);
// ⚠️ 必须重新渲染,否则 Layui 样式不生效
form.render('select');
// 🔄 联动后是否自动刷新表格?根据业务开启
if (pid !== '' || $('select[name="cate_id"]').val() !== '') {
table.reload('dataTable', {
where: form.val('table-search'), // 自动带上当前表单所有条件
page: { curr: 1 } // 联动后回到第一页
});
}
});
// 重置按钮逻辑(重要!)
$('button[type="reset"]').on('click', function() {
// 重置表单
form.val('table-search', { cate_pid: '', cate_id: '' });
// 重置子级下拉框
$('select[name="cate_id"]').html('<option value="">全部</option>');
form.render('select');
// 刷新表格到初始状态
table.reload('dataTable', { where: {} });
});
```
---
### 💡 关键细节 & 最佳实践
| 场景 | 处理方式 |
|------|----------|
| **数据量大会卡慢** | 不要一次性把所有子选项写死。改用 `$.ajax` 懒加载:选择父级后请求 `/api/sub?pid=xxx`,返回后动态拼接 `option`。 |
| **父级选“全部”时** | 建议清空子级下拉框或恢复默认提示文案,避免用户误提交旧条件。 |
| **多个层级联动** | 采用链式监听,每级复用同一套 `renderSelect(name, parentId)` 封装函数。 |
| **防抖优化** | 若联动频繁触发表格请求,建议包裹 `lodash.debounce` 或手动节流,避免重复请求。 |
| **表单校验联动** | 子级下拉框若设置为必填,联动时需同时更新 `lay-verify="required"` 属性。 |
---
### 📌 常见问题排查
1. **样式没变/变成原生下拉?** → 忘记写 `form.render('select')`
2. **事件触发多次或错乱?** → 全局 `form.on('select')` 易冲突,改为 `form.on('select(cate_pid)')`
3. **联动后表格没刷新?** → `table.reload('id', {where: form.val('filter')})` 中的 `where` 未正确传递当前表单值。
4. **PHP模板变量注入问题** → 确保 `notes.cate_sub` 在 JS 执行前已完成赋值(可放在 `<script>` 顶部或 `{block}` 头部)。
你的原始思路完全正确,只需补充 **精准事件绑定**、**渲染时机** 和 **表格查询同步** 即可无缝接入现有项目。如需适配 AJAX 动态加载或多级树形联动,可提供具体数据结构,我为你输出定制版本。