在 sessionStorage 中保存 Javascript 对象

SessionStorage 和 LocalStorage 允许在 Web 浏览器中保存键/值对。这个值必须是一个字符串,而保存 js 对象并非易事。

var user = {'name':'John'};
sessionStorage.setItem('user', user);
var obj = sessionStorage.user; // obj='[object Object]' Not an object

现在,您可以通过将对象序列化为 JSON,然后反序列化它们来恢复对象来避免这种限制。但是 StorageAPI 总是通过 setItemgetItem方法。

sessionStorage.setItem('user', JSON.stringify(user));
var obj = JSON.parse(sessionStorage.getItem('user')); // An object :D

我可以避免这个限制吗?

我只是想执行这样的东西:

sessionStorage.user.name; // 'John'
sessionStorage.user.name = 'Mary';
sessionStorage.user.name // 'Mary'

我已经尝试使用 defineGetterdefineSetter方法来拦截调用,但这是一项乏味的工作,因为我必须定义所有属性,而我的目标是不知道将来的属性。

328209 次浏览

您可以使用 Web Storage API 提供的访问器,也可以编写一个包装器/适配器。从您提到的 defeGetter/defeSetter 问题来看,似乎编写一个包装器/适配器对您来说太繁重了。

我真的不知道该怎么跟你说。也许你可以重新评估一下你对什么是“荒谬的限制”的看法。Web 存储 API 就是它应该是的那样,一个键/值存储。

你能不能不“字符串化”你的对象... 然后使用 sessionStorage.setItem()存储你的对象的字符串表示... 然后当你需要它 sessionStorage.getItem(),然后使用 $.parseJSON()得到它回来?

工作示例 http://jsfiddle.net/pKXMa/

用例:

 sesssionStorage.setObj(1,{date:Date.now(),action:'save firstObject'});
sesssionStorage.setObj(2,{date:Date.now(),action:'save 2nd object'});
//Query first object
sesssionStorage.getObj(1)
//Retrieve date created of 2nd object
new Date(sesssionStorage.getObj(1).date)

空气污染指数

Storage.prototype.setObj = function(key, obj) {


return this.setItem(key, JSON.stringify(obj))
};
    

Storage.prototype.getObj = function(key) {
return JSON.parse(this.getItem(key))
};

解决方案是在调用 sessionStorage 上的 setItem 之前对对象进行字符串化。

var user = {'name':'John'};
sessionStorage.setItem('user', JSON.stringify(user));
var obj = JSON.parse(sessionStorage.user);
    var user = {'name':'John'};
sessionStorage['user'] = JSON.stringify(user);
console.log(sessionStorage['user']);

这是一个动态解决方案,适用于包括对象在内的所有值类型:

class Session extends Map {
set(id, value) {
if (typeof value === 'object') value = JSON.stringify(value);
sessionStorage.setItem(id, value);
}


get(id) {
const value = sessionStorage.getItem(id);
try {
return JSON.parse(value);
} catch (e) {
return value;
}
}
}

然后:

const session = new Session();


session.set('name', {first: 'Ahmed', last : 'Toumi'});
session.get('name');

你也可以使用 商店图书馆为你执行它与跨浏览器的能力。

例如:

// Store current user
store.set('user', { name:'Marcus' })


// Get current user
store.get('user')


// Remove current user
store.remove('user')


// Clear all keys
store.clearAll()


// Loop over all stored values
store.each(function(value, key) {
console.log(key, '==', value)
})

会话存储不能支持任意对象,因为它可能包含在页面重新加载后无法重新构造的函数文字(读闭包)。

您可以创建两个包装器方法,用于从会话存储中保存和检索对象。

function saveSession(obj) {
sessionStorage.setItem("myObj", JSON.stringify(obj));
return true;
}


function getSession() {
var obj = {};
if (typeof sessionStorage.myObj !== "undefined") {
obj = JSON.parse(sessionStorage.myObj);
}
return obj;
}

像这样使用它:-获取对象,修改一些数据,然后保存回来。

var obj = getSession();


obj.newProperty = "Prod"


saveSession(obj);

CustomHook 是使用 React 17.0.1中的 sessionStorage 将令牌存储为对象的最佳方法之一。

遵循以下指示:

  1. 在自定义函数中实现 sessionStorage get/set:

    export default function useToken() {
    const getToken = () => {
    const tokenString = sessionStorage.getItem('token');
    const userToken = JSON.parse(tokenString);
    return userToken?.token;
    };
    
    
    const [token, setToken] = useState(getToken());
    
    
    const saveToken = (userToken) => {
    sessionStorage.setItem('token', JSON.stringify(userToken));
    setToken(userToken.token);
    };
    
    
    
    
    return {
    setToken: saveToken,
    token,
    };
    }
    
  2. 这个函数可以被导入并用作其他组件的钩子,例如:

     import useToken from './useToken';
    
    
    const { token, setToken} = useToken(); // call CustomHook
    
    
    const handleSubmit = async (event) => {
    event.preventDefault();
    // call functionAPI
    const token = await loginUser({
    username,
    password,
    });
    setToken(token); // AUTOMATICALLY token will be stored to sessionStorage of browser
    };