将日期保存到本地存储

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 的,因为您没有使用编译器来强制执行类型安全。 这实际上意味着实际验证函数参数参数的类型是否正确(例如stringobjectDate 等)并且它们的值在预期范围内(例如,不允许 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 中)。 下面的代码中有相当多的重复性(例如,loadTodosloadCalendar 函数几乎相同,备用它们使用的 localStorage 键值,因此可以在不重复逻辑的情况下重写. 这是留给读者的练习。

【讨论】:

谢谢戴!我试过了,但得到了这个“未捕获的引用错误:未定义 KEY_TODOS”。 @MirandaNilhag 这是一个错字。我现在已经修好了,但我希望你能自己解决这个问题。

以上是关于将日期保存到本地存储的主要内容,如果未能解决你的问题,请参考以下文章

将表单数据保存到本地存储并在刷新时显示

从本地存储中保存和检索日期

将数据保存到本地存储

将号码数据保存到本地存储

如何将反应js状态保存到本地存储中

Angular 6:将数据保存到本地存储