这篇文章分享一下自己使用sessionStorage遇到的一个小问题,以后遇到要避坑。
需求是easyui表格的单元格编辑,点击保存的时候会结束当前行的编辑,然后修改editingId(当前编辑行记录的ID)。
目录
一、待解决问题
如图,点击修改按钮时无响应,也没有报错。
二、完整的页面代码
menu_list.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/themes/icon.css"/>
<link rel="stylesheet" href="/css/themes/default/easyui.css" />
<title>系统管理>>菜单列表</title>
<script src="/js/public/jquery.min.js"></script>
<script src="/js/easyui/jquery.easyui.min.js"></script>
<script src="/js/easyui/easyui-lang-zh_CN.js"></script>
<script src="/js/public/util.js"></script>
<script src="/js/public/public.js"></script>
<script src="/js/public/sessionStorage.js"></script>
<script src="/js/menu_list.js"></script>
</head>
<body>
<div>
<a href="javascript:" class="easyui-linkbutton" onclick="insert()">添加</a>
<a href="javascript:" class="easyui-linkbutton" onclick="edit()">修改</a>
<a href="javascript:" class="easyui-linkbutton" onclick="save()">保存</a>
<a href="javascript:" class="easyui-linkbutton" onclick="cancel()">取消</a>
<a href="javascript:" class="easyui-linkbutton" onclick="expandAll()">展开全部</a>
<a href="javascript:" class="easyui-linkbutton" onclick="collapseAll()">折叠全部</a>
</div>
<div id="mm" class="easyui-menu" style="width:120px;">
<div onclick="append()" data-options="iconCls:'icon-add'">添加</div>
<div onclick="removeIt()" data-options="iconCls:'icon-remove'">删除</div>
<div class="menu-sep"></div>
<div onclick="collapse()">折叠</div>
<div onclick="expand()">展开</div>
</div>
<table id="menu_treegrid"></table>
</body>
</html>
menu_list.js
let parentId;
let data = {
id: "",
name: "xxx",
url: "",
icon: "icon-xxx"
};
/**
* 添加
*/
function insert() {
let menuId = new Date().getTime();
let treegrid = $("#menu_treegrid");
treegrid.treegrid("append",{
data: [{
id: menuId,
name: "xxx",
url: "/html/xxx",
icon: "icon-xxx"
}]
});
// 保存editingId到sessionStorage
storage("editingId", menuId);
// 开启行编辑
treegrid.treegrid("beginEdit", menuId);
}
/**
* 修改
*/
function edit() {
let editingId = getStorage("editingId");
console.log(editingId);
if (editingId) {
$("#menu_treegrid").treegrid("select", editingId);
} else {
let row = $("#menu_treegrid").treegrid("getSelected");
console.log("开始编辑行:");
console.log(row);
if (row) {
storage("editingId", row.id);
$("#menu_treegrid").treegrid("beginEdit", row.id);
}
}
}
/**
* 保存
*/
function save() {
let editingId = getStorage("editingId");
if (editingId) {
let treegrid = $("#menu_treegrid");
if (editingId) {
// 只有结束编辑才能获取到最新的值
treegrid.treegrid("endEdit", editingId);
let postData = {
id: editingId,
name: data.name,
url: data.url,
icon: data.icon,
parentId: parentId
};
console.log(postData);
storage("editingId", undefined);
// post("/menu/updateById", postData, function () {
// storage("editingId", undefined);
// }, error);
}
}
}
/**
* 取消
*/
function cancel() {
let editingId = getStorage("editingId");
if (editingId) {
$("#menu_treegrid").treegrid("cancelEdit", editingId);
storage("editingId", undefined);
}
}
/**
* 折叠全部
*/
function collapseAll() {
$("#menu_treegrid").treegrid("collapseAll");
}
/**
* 展开全部
*/
function expandAll() {
$("#menu_treegrid").treegrid("expandAll");
}
/**
* 添加
*/
function append() {
let menuId = new Date().getTime();
let treegrid = $("#menu_treegrid");
let node = treegrid.treegrid("getSelected");
parentId = node.id;
storage("editingId", menuId);
treegrid.treegrid("append",{
parent: node.id,
data: [{
id: menuId,
name: "xxx",
url: "",
icon: "icon-xxx"
}]
});
let editingId = getStorage("editingId");
treegrid.treegrid("beginEdit", editingId);
}
/**
* 删除
*/
function removeIt() {
let node = $("#menu_treegrid").treegrid("getSelected");
if (node) {
$("#menu_treegrid").treegrid("remove", node.id);
}
}
/**
* 折叠
*/
function collapse() {
let node = $("#menu_treegrid").treegrid("getSelected");
if (node) {
$("#menu_treegrid").treegrid("collapse", node.id);
}
}
/**
* 展开
*/
function expand() {
let node = $("#menu_treegrid").treegrid("getSelected");
if (node) {
$("#menu_treegrid").treegrid("expand", node.id);
}
}
$(document).ready(function() {
$("#menu_treegrid").treegrid({
url: "/menu/listTreeGrid",
method: "get",
idField: "id",
treeField: "name",
fitColumns: true,
pagination: true,
pageSize: 10,
pageList: [10, 20, 50, 100],
columns:[[
{title: "菜单编号", field: "id", hidden: true},
{title: "菜单名称", field: "name", align: "left", editor: "textbox", width: 100},
{title: "图标样式", field: "icon", align: "left", editor: "textbox", width: 100},
{title: "页面地址", field: "url", align: "left", editor: "textbox", width: 200,
formatter: function(value) {
if (value) {
return "<a href='" + value + "'>" + value + "</a>";
} else {
return "<div>/</div>";
}
}
}
]],
onAfterEdit: function (row, changes) {
console.log(changes);
data = {
id: row.id,
name: row.name ? row.name : changes.name,
url: row.url ? row.url : changes.url,
icon: row.icon ? row.icon : changes.icon
};;
},
onContextMenu: function (e, row) {
e.preventDefault();
$(this).treegrid("select", row.id);
$("#mm").menu("show",{
left: e.pageX,
top: e.pageY
});
}
}).treegrid("clientPaging");
});
(function($) {
function pagerFilter(data) {
if ($.isArray(data)) { // is array
data = {
total: data.length,
rows: data
}
}
let dg = $(this);
let state = dg.data("treegrid");
let opts = dg.treegrid("options");
let pager = dg.treegrid("getPager");
pager.pagination({
onSelectPage:function(pageNum, pageSize) {
opts.pageNumber = pageNum;
opts.pageSize = pageSize;
pager.pagination("refresh",{
pageNumber:pageNum,
pageSize:pageSize
});
dg.treegrid("loadData",state.originalRows);
}
});
if (!state.originalRows){
state.originalRows = data.rows;
}
let topRows = [];
let childRows = [];
$.map(state.originalRows, function(row){
row._parentId ? childRows.push(row) : topRows.push(row);
});
data.total = topRows.length;
let start = (opts.pageNumber-1)*parseInt(opts.pageSize);
let end = start + parseInt(opts.pageSize);
data.rows = $.extend(true,[],topRows.slice(start, end).concat(childRows));
return data;
}
let appendMethod = $.fn.treegrid.methods.append;
let loadDataMethod = $.fn.treegrid.methods.loadData;
$.extend($.fn.treegrid.methods, {
clientPaging: function(jq) {
return jq.each(function() {
let state = $(this).data("treegrid");
let opts = state.options;
opts.loadFilter = pagerFilter;
let onBeforeLoad = opts.onBeforeLoad;
opts.onBeforeLoad = function(row,param) {
state.originalRows = null;
onBeforeLoad.call(this, row, param);
}
$(this).treegrid("loadData", state.data);
$(this).treegrid("reload");
});
},
loadData: function(jq, data) {
jq.each(function() {
$(this).data("treegrid").originalRows = null;
});
return loadDataMethod.call($.fn.treegrid.methods, jq, data);
},
append: function(jq, param) {
return jq.each(function() {
let state = $(this).data("treegrid");
if (state.options.loadFilter == pagerFilter){
$.map(param.data, function(row) {
row._parentId = row._parentId || param.parent;
state.originalRows.push(row);
});
$(this).treegrid("loadData", state.originalRows);
} else {
appendMethod.call($.fn.treegrid.methods, jq, param);
}
})
}
});
})(jQuery);
三、具体业务逻辑
添加数据
当点击添加按钮的时候,会在表格末尾添加一行记录,并开启行编辑,使用了sessionStorage保存正在编辑的行数据的ID。
/**
* 添加
*/
function insert() {
let menuId = new Date().getTime();
let treegrid = $("#menu_treegrid");
treegrid.treegrid("append",{
data: [{
id: menuId,
name: "xxx",
url: "/html/xxx",
icon: "icon-xxx"
}]
});
// 保存editingId到sessionStorage
storage("editingId", menuId);
// 开启行编辑
treegrid.treegrid("beginEdit", menuId);
}
保存数据
点击保存会修改editingId的值为undefined,相当于删除
/**
* 保存
*/
function save() {
let editingId = getStorage("editingId");
if (editingId) {
let treegrid = $("#menu_treegrid");
if (editingId) {
// 只有结束编辑才能获取到最新的值
treegrid.treegrid("endEdit", editingId);
let postData = {
id: editingId,
name: data.name,
url: data.url,
icon: data.icon,
parentId: parentId
};
console.log(postData);
// 修改editingId的值为undefined,相当于删除
storage("editingId", undefined);
// post("/menu/updateById", postData, function () {
// storage("editingId", undefined);
// }, error);
}
}
}
编辑数据
选中表格一行,点击编辑按钮,就会根据editingId的值来判断当前有没有行在编辑,如果有的话,选中当前行,但是不结束正在编辑的行。如果没有在编辑的数据行,则开启当前选中行的编辑。
/**
* 修改
*/
function edit() {
let editingId = getStorage("editingId");
console.log(editingId);
if (editingId) {
$("#menu_treegrid").treegrid("select", editingId);
} else {
let row = $("#menu_treegrid").treegrid("getSelected");
console.log("开始编辑行:");
console.log(row);
if (row) {
storage("editingId", row.id);
$("#menu_treegrid").treegrid("beginEdit", row.id);
}
}
}
四、问题分析
点击修改按钮无反应,但是并没有报错,问题很显然,是一直走的if分支,一直在选中当前行。
所以,问题的关键就在editingId的值,上面通过浏览器打印出来的值为undefined,很显然没有什么问题。
但是,致命的就是这里,这里打印的undefined并不是未定义,而是字符串的"undefined"。
直接打印undefined是灰色的,如图,下面的那个是真的undefined
五、问题解决
方案一:既然不能直接存undefined,那么就存一个空字符串进去,问题完美解决~
/**
* 保存
*/
function save() {
let editingId = getStorage("editingId");
if (editingId) {
let treegrid = $("#menu_treegrid");
if (editingId) {
// 只有结束编辑才能获取到最新的值
treegrid.treegrid("endEdit", editingId);
let postData = {
id: editingId,
name: data.name,
url: data.url,
icon: data.icon,
parentId: parentId
};
storage("editingId", "");
}
}
}
方案二:从localStorage中删除数据
/**
* 保存
*/
function save() {
let editingId = getStorage("editingId");
if (editingId) {
let treegrid = $("#menu_treegrid");
if (editingId) {
// 只有结束编辑才能获取到最新的值
treegrid.treegrid("endEdit", editingId);
let postData = {
id: editingId,
name: data.name,
url: data.url,
icon: data.icon,
parentId: parentId
};
localStorage.removeItem("editingId");
}
}
}