javascript的webstorage数据存储问题,不能直接存undefined

文章讲述了作者在使用easyui表格进行单元格编辑时遇到的问题,即点击修改按钮无响应。问题在于存储的editingId值为字符串undefined而非真正的undefined。文章提供了两种解决方案:存储空字符串或从localStorage中删除数据。
摘要由CSDN通过智能技术生成

这篇文章分享一下自己使用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");
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值