storage数据存储问题,不能存undefined

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

			console.log(postData);
			storage("editingId", "");
		}
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/111247.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】Docker的应用包含Sandbox、PaaS、Open Solution以及IT运维概念的详细讲解

前言 作者简介&#xff1a; 辭七七&#xff0c;目前大二&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&…

Spring MVC的常用注解(设置响应篇)

目录 1.返回静态页面 2.返回数据 3.返回HTML代码片段 4.返回json 5.设置状态码 6.设置Header &#xff08;1&#xff09;.设置 Content-Type &#xff08;2&#xff09;.设置其他Header 推荐先看前篇博客Spring MVC的常用注解&#xff08;接收请求数据篇&#xff09; 接收…

UE4/UE5 设置widget中text的字体Outline

想要在蓝图中控制Widget 中的 text字体&#xff0c;对字体outline参数进行设置。 但是蓝图中无法直接获取设置outline参数的方法&#xff1a; 没有outline相关的蓝图函数 该参数本身是在Font类别下的扩展&#xff0c;所以只要获取设置Font参数即可进行outline的设置 text连出…

11、插件注入到vue实例中

新建插件 nuxt-demo2\plugins\vue-inject.js import Vue from "vue"Vue.prototype.$test function (str) {console.log(str) }配置插件 nuxt-demo2\nuxt.config.js export default {...// Plugins to run before rendering page: https://go.nuxtjs.dev/config-…

python基于VGG19实现图像风格迁移

目录 1、原理 2、代码实现 1、原理 图像风格迁移是一种将一张图片的内容与另一张图片的风格进行合成的技术。 风格&#xff08;style&#xff09;是指图像中不同空间尺度的纹理、颜色和视觉图案&#xff0c;内容&#xff08;content&#xff09;是指图像的高级宏观结构。 实…

计算机网络重点概念整理-第四章 网络层【期末复习|考研复习】

计算机网络复习系列文章传送门&#xff1a; 第一章 计算机网络概述 第二章 物理层 第三章 数据链路层 第四章 网络层 第五章 传输层 第六章 应用层 第七章 网络安全 计算机网络整理-简称&缩写 文章目录 前言四、网络层4.1 网络层功能4.1.1 电路交换、报文交换与分组交换4.1…

电商数据采集抓取封装数据、淘宝、天猫、京东等平台商品详情API接口参数详解

电商数据采集抓取数据、淘宝、天猫、京东等平台的电商数据抓取&#xff0c;网页爬虫、采集网站数据、网页数据采集软件、python爬虫、HTM网页提取、APP数据抓包、APP数据采集、一站式网站采集技术、BI数据的数据分析、数据标注等成为大数据发展中的热门技术关键词。那么电商数据…

【git】git拉取代码报错,fatal: refusing to merge unrelated histories问题解决

大家好&#xff0c;我是好学的小师弟。今天准备将之前写的代码&#xff0c;拉到新的工程文件夹(仓库)下面&#xff0c;用了pull命令&#xff0c;结果报错了&#xff0c;报错截图如下 $ git pull https://gitee.com/* #仓库地址 fatal: refusing to merge unrelated histor…

12、SpringCloud -- redis库存和redis预库存保持一致、优化后的压测效果

目录 redis库存和redis预库存保持一致问题的产生需求:代码:测试:优化后的压测效果之前的测试数据优化后的测试数据redis库存和redis预库存保持一致 redis库存是指初始化是从数据库中获取最新的秒杀商品列表数据存到redis中 redis的预库存是指每个秒杀商品每次成功秒杀之后…

Spring循环依赖处理

循环依赖是指两个或多个组件之间相互依赖&#xff0c;形成一个闭环&#xff0c;从而导致这些组件无法正确地被初始化或加载。这种情况可能会在软件开发中引起问题&#xff0c;因为循环依赖会导致初始化顺序混乱&#xff0c;组件之间的关系变得复杂&#xff0c;甚至可能引发死锁…

汉诺塔问题

作者本文的目标是利用递归求解汉诺塔的具体步骤 目录 汉诺塔是什么游戏思路1.最简单的情况——一个圆盘依次类推&#xff0c;增加盘子个数2.两个圆盘3.三个圆盘解释递归过程 完整代码 汉诺塔是什么 汉诺塔&#xff08;Tower of Hanoi&#xff09;&#xff0c;又称河内塔&#x…

Kubernetes - Ingress HTTP 升级 HTTPS 配置解决方案(新版本v1.21+)

之前我们讲解过 Kubernetes - Ingress HTTP 搭建解决方案&#xff0c;并分别提供了旧版本和新版本。如果连 HTTP 都没搞明白的可以先去过一下这两篇 Kubernetes - Ingress HTTP 负载搭建部署解决方案_放羊的牧码的博客-CSDN博客Kubernetes - Ingress HTTP 负载搭建部署解决方案…

学习笔记---更进一步的双向链表专题~~

目录 1. 双向链表的结构&#x1f98a; 2. 实现双向链表&#x1f41d; 2.1 要实现的目标&#x1f3af; 2.2 创建初始化&#x1f98b; 2.2.1 List.h 2.2.2 List.c 2.2.3 test.c 2.2.4 代码测试运行 2.3 尾插打印头插&#x1fabc; 思路分析 2.3.1 List.h 2.3.2 List.…

企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及审…

Ceph入门到精通-bluestore IO流程及导入导出

bluestore 直接管理裸设备&#xff0c;实现在用户态下使用linux aio直接对裸设备进行I/O操作 写IO流程&#xff1a; 一个I/O在bluestore里经历了多个线程和队列才最终完成&#xff0c;对于非WAL的写&#xff0c;比如对齐写、写到新的blob里等&#xff0c;I/O先写到块设备上&am…

0003net程序设计-net旅游景点推荐系统

文章目录 摘 要目录系统设计开发环境 摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#…

多模态 多引擎 超融合 新生态!2023亚信科技AntDB数据库8.0产品发布

9月20日&#xff0c;以“多模态 多引擎 超融合 新生态”为主题的亚信科技AntDB数据库8.0产品发布会成功举办&#xff0c;从技术和生态两个角度全方位展示了AntDB数据库第8次大型能力升级和生态建设成果。浙江移动、用友、麒麟软件、华录高诚、金云智联等行业伙伴及业界专家共同…

Goland连接服务器/虚拟机远程编译开发

创建SSH连接 SSH用于与远程服务器建立连接 Settings -> Tools -> SSH Configurations 添加新的ssh连接&#xff0c;Host为ip地址&#xff0c;Username为用户名&#xff0c;认证方式这里选择密码验证 全部填完后可以点击Test Connection测试连接是否成功 创建Deployment…

nginx 转发数据流文件

1.问题描述 后端服务&#xff0c;从数据库中查询日志&#xff0c;并生成表格文件返回静态文件。当数据量几兆时&#xff0c;返回正常&#xff0c;但是超过几十兆&#xff0c;几百兆&#xff0c;就会超过网关的连接超时时间30秒。 时序图 这里面主要花费时间的地方在&#xff…

SPSS单样本t检验

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…