直接存整个表格 DOM 会出错,因为 outerHTML 只保存静态结构,不包含用户操作状态(如 checkbox 勾选、input 值),且重新渲染后事件监听器丢失;正确做法是只存筛选参数对象并用 JSON 序列化,在 DOM 加载后填充表单并主动触发过滤逻辑。

为什么直接存整个表格 DOM 会出错
很多人一上来就用 sessionStorage.setItem('tableState', document.querySelector('#myTable').outerHTML),结果刷新后筛选条件丢了,或者表头错乱。根本原因是:outerHTML 只保存静态结构,不包含用户操作产生的状态(比如 checkbox 是否勾选、input 的 value 值),而且重新 innerHTML 渲染后事件监听器全丢,onchange 或 onclick 不再生效。
正确做法是只存「筛选参数」,不是存 DOM。比如用户在「状态」列选了 active,在「日期范围」填了 2024-01-01 到 2024-06-30,这些才是该存的键值对。
- 存的是
{ status: 'active', dateFrom: '2024-01-01', dateTo: '2024-06-30' },不是整张表 - 恢复时用 JS 主动设置
input.value、select.value、checkbox.checked - 必须在 DOM 加载完成(
DOMContentLoaded)后再读取并填充,否则元素还没挂载,赋值无效
如何序列化和反序列化筛选条件
sessionStorage 只支持字符串,但筛选条件通常是对象。别手写拼接字符串——容易漏转义、难维护。统一用 JSON.stringify() 和 JSON.parse(),但要注意:函数、undefined、Date 对象不能被 JSON 序列化,所以筛选条件里不要放这些类型。
示例:一个带日期输入的筛选表单
立即学习“前端免费学习笔记(深入)”;
使用 Puppeteer + Chrome 将 HTML 渲染为中文 PDF,自动处理图表等待、Tab 展开、动画、测高、白边消除、防分页,适用于看板、报表、网页和交互图表转 PDF。
const filterForm = document.getElementById('filter-form');
const saveFilterState = () => {
const data = {
status: filterForm.status.value,
keyword: filterForm.keyword.value.trim(),
dateFrom: filterForm.dateFrom.value,
dateTo: filterForm.dateTo.value
};
sessionStorage.setItem('tableFilterState', JSON.stringify(data));
};
const loadFilterState = () => {
const saved = sessionStorage.getItem('tableFilterState');
if (!saved) return;
try {
const state = JSON.parse(saved);
Object.keys(state).forEach(key => {
const el = filterForm[key];
if (el && el.type === 'checkbox') {
el.checked = state[key];
} else if (el) {
el.value = state[key];
}
});
} catch (e) {
// JSON 解析失败,说明数据损坏,直接清除
sessionStorage.removeItem('tableFilterState');
}
};
- 每次提交或切换筛选项后调用
saveFilterState() - 页面加载后立即调用
loadFilterState(),再触发一次过滤逻辑(别忘了!) - 捕获
JSON.parse()异常,避免因旧数据格式变更导致脚本中断
筛选逻辑与 sessionStorage 如何联动执行
存/取只是搬运数据,真正起作用的是「应用筛选」这一步。很多人存了也取了,但没重新跑过滤函数,结果界面看起来没变化。
关键点在于:加载完筛选条件后,必须主动触发一次过滤,而不是等用户点「搜索」按钮。
- 把过滤逻辑抽成独立函数,比如
applyTableFilter(filterState) -
loadFilterState()最后加一行applyTableFilter(state); - 如果过滤依赖异步数据(如从 API 拉表格行),确保
applyTableFilter在数据 ready 后才执行,或加个 pending 标志位 - 避免重复触发:如果用户手动改筛选项,先
saveFilterState(),再applyTableFilter();不要在 input 事件里每敲一个字就过滤一次,加防抖(setTimeout+clearTimeout)
兼容性与边界情况处理
sessionStorage 在所有现代浏览器都支持,但有两个现实问题常被忽略:
- 隐私模式下部分浏览器(如 Safari)会拒绝写入
sessionStorage,此时setItem抛SecurityError,需包裹 try/catch - 超过 5MB(实际约 4–5MB)会抛
QuotaExceededError,但筛选条件极小,几乎不可能触达,无需专门处理容量 - 用户清空浏览器缓存或关闭所有标签页后,
sessionStorage自动清空——这是设计使然,不是 bug - 多标签页间不共享
sessionStorage,A 标签页存的,B 标签页读不到;如需跨页同步,改用localStorage+storage事件监听
最易被跳过的细节:筛选条件字段名必须和表单元素的 name 或 id 严格一致,否则 filterForm[key] 拿不到元素,赋值静默失败。建议统一用 id 作为 key 名,避免歧义。


















