将日期保存到本地存储
Posted
技术标签:
【中文标题】将日期保存到本地存储【英文标题】:Save dates to local storage 【发布时间】:2022-01-23 18:32:54 【问题描述】:我正在构建一个带有同步待办事项列表的日历。我正在尝试根据用户输入将特定日期保存到本地存储。目前,待办事项已保存到本地存储,并显示在带有文本的待办事项列表和日历中,但如果我刷新页面,日历中的待办事项就会消失。
在本地存储中写入值:[object htmlInputElement]
function saveTodosToLS()
const todosAsString = JSON.stringify(todos);
localStorage.setItem("todos", todosAsString);
function loadTodos()
const todosAsString = localStorage.getItem('todos');
todos = JSON.parse(todosAsString || '[]');
这是我苦苦挣扎的部分
function saveCalendarToLS()
const todoDateAsString = Date.parse('dateOfTodos');
todoDateAsString = JSON.stringify(dateOfTodos);
localStorage.setItem('dateOfTodos', todoDateAsString);
function loadTodosInLS()
const todoDateAsString = localStorage.getItem('dateOfTodos');
dateOfTodos = Date.parse(todoDateAsString || '[]');
【问题讨论】:
Date.parse('dateOfTodos')
是什么意思
@MirandaNilhag JSON 可以对数字进行字符串化。根据我的经验,将 javascript Date
对象序列化为 JSON 的最可靠方法是仅保存 Date
的内部 Unix 时间戳(来自 getTime()
),然后使用 Date(number)
构造函数重新水化。
您不能将 DOM 元素对象(如 HTMLInputElement
)传递给 localStorage
。你只能传递“POJO”对象(Plain Ol' JavaScript Objects)。
我认为你应该更新那部分 JSON.stringify(todoDateAsString);
编程时经常做的一件有用的事情是在出现问题时查看中间结果。在这种情况下,在浏览器控制台中运行 Date.parse('dateOfTodos');
,并在运行问题中的代码后查看本地存储值的值可能会提供信息。
【参考方案1】:
您不应该使用使用全局变量(或任何类型的共享状态,实际上)来传递数据。当数据通过函数参数传入并通过返回值返回时,程序更容易理解。
练习防御性编程。这在 JavaScript 中是完全 essential 的,因为您没有使用编译器来强制执行类型安全。
这实际上意味着实际验证函数参数参数的类型是否正确(例如string
、object
、Date
等)并且它们的值在预期范围内(例如,不允许 1000 年后的 Date
值)。
您的 Date.parse
调用完全不正确(为什么要传递非日期字符串文字?)
我会这样做:
(请参阅代码下方的注释项目符号列表)
const LOCALSTORAGE_KEY_TODOS = "todos";
function saveTodos( todosArray )
if( !Array.isArray( todosArray ) ) throw new Error( "Expected 'todosArray' to be an array but encountered " + ( typeof todosArray ) ); // Defensive programing!
const todosAsJson = JSON.stringify( todosArray );
window.localStorage.setItem( LOCALSTORAGE_KEY_TODOS, todosAsJson );
/** Returns an array of todo objects. Returns an empty array if nothing is saved in the store. */
function loadTodos()
const todosAsJson = window.localStorage.getItem( LOCALSTORAGE_KEY_TODOS );
if( todosAsJson )
try
const todos = JSON.parse( todosAsJson );
if( Array.isArray( todos ) ) return todos;
catch( err )
console.error( "Couldn't load TODOs: %o", err );
return [];
function saveCalendar( date, todos )
if( !isDate( date ) ) throw new Error( "Expected 'date' to be a Date object." );
if( !Array.isArray( todosArray ) ) throw new Error( "Expected 'todosArray' to be an array but encountered " + ( typeof todosArray ) );
const dateKey = 'CALENDAR_' + getDateOnlyString( date );
const todosAsJson = JSON.stringify( todosArray );
window.localStorage.setItem( dateKey, todosAsJson );
/** Returns an array of todo objects. Returns an empty array if nothing is saved in the store for that date. The time component of 'date' is ignored. */
function loadCalendar( date )
if( !isDate( date ) ) throw new Error( "Expected 'date' to be a Date object." );
const dateKey = 'CALENDAR_' + getDateOnlyString( date );
//
const todosAsJson = window.localStorage.getItem( dateKey );
if( todosAsJson )
try
const todos = JSON.parse( todosAsJson );
if( Array.isArray( todos ) ) return todos;
catch( err )
console.error( "Couldn't load TODOs: %o", err );
return [];
/** Returns boolean true or false */
function isDate( value )
// https://***.com/questions/643782/how-to-check-whether-an-object-is-a-date
return value instanceof Date && ( typeof value.getMonth === 'function' );
/** Returns `date` formatted as ISO 8601 yyyy-MM-dd */
function getDateOnlyString( date )
// HACK: https://***.com/questions/25159330/how-to-convert-an-iso-date-to-the-date-format-yyyy-mm-dd
return date.toISOString().substring(0,10); // "if it works..."
避免发明你自己的首字母缩略词:我看到你使用“LS
”是localStorage
的简写,但是这在 JavaScript 社区中并不常见,所以我会避免使用它并直接称它为是:localStorage
。
您尚未发布 TODO object
的定义或规范,因此我的以下代码不会验证或验证有关 TODO 对象的任何内容,除非它们实际上是 object
值。
避免使用魔法文字,无论是字符串还是数字。当您需要集合的一致键字符串(如 window.localStorage
)时,您应该使用命名常量(例如 const LOCALSTORAGE_KEY_TODOS = 'todos';
)。
请记住,JavaScript 中的 Date
对象实际上表示日期和时间值,因此您不能只使用任何旧的Date
对象来表示只是 一个日期。如果您使用Date
或它的Unix时间戳值(来自Date.getTime()
),您会发现不可能从localStorage
检索现有项目,因为它们的键将每毫秒更改一次,而不是一次-每天。
我下面的代码通过使用toISOString()
来获得一个完整 ISO 8601 日期+时间字符串(形式为yyyy-MM-dd HH:mm:sszzz
)and uses .substring(0,10)
as a cheap-trick 来解决这个问题 -日期组件,以便返回的字符串仅包含日期信息(位于 function getDateOnlyString
中)。
下面的代码中有相当多的重复性(例如,loadTodos
和 loadCalendar
函数几乎相同,备用它们使用的 localStorage
键值,因此可以在不重复逻辑的情况下重写. 这是留给读者的练习。
【讨论】:
谢谢戴!我试过了,但得到了这个“未捕获的引用错误:未定义 KEY_TODOS”。 @MirandaNilhag 这是一个错字。我现在已经修好了,但我希望你能自己解决这个问题。以上是关于将日期保存到本地存储的主要内容,如果未能解决你的问题,请参考以下文章