放入本地存储时,对象的属性不会修改元素的值

时间:2019-11-04 05:53:05

标签: javascript object local-storage

我创建了一个对象,该对象存储DOM输入的键控代码。最初,每个输入均设置有与键控代码相关的默认值,更新后,键控代码会发生变化,但输入值不确定。为什么会这样?

    const inputs = localStorage.keys ? JSON.parse(localStorage.keys) : [
       {elem: document.getElementById("x1split_input"), key: null},
       {elem: document.getElementById("x2split_input"), key: 81},
       {elem: document.getElementById("x16split_input"), key: 16},
       {elem: document.getElementById("respawn_input"), key: 82}
    ]

    for(let obj of inputs){
       obj.elem.value = keyboardMap[obj.key] 
       obj.elem.onkeyup = (key) => {
           obj.key = key.keyCode
           obj.elem.value = keyboardMap[obj.key] 
           localStorage.setItem("keys", JSON.stringify(inputs))
      }
    }
    console.log(localStorage.keys) 
    //[{"elem":{},"key":null},{"elem":{"value":"Q"},"key":81},{"elem":{"value":"SHIFT"},"key":16},{"elem":{"value":"A"},"key":65}]

1 个答案:

答案 0 :(得分:1)

一旦从“存储”区域检索了存储的对象,您将丢失每个对象的.elem所指向的Element。您所拥有的只是一个普通对象,并且在这些对象上添加onkeyup方法不会像它们是实际元素那样。

const inputs = [ { elem: document.getElementById("my-input") } ];
console.log( inputs ); // [ { "elem": <input id="my-input"> } ]

const in_storage = JSON.stringify( inputs );
console.log( in_storage ); // '[{"elem":{}}]'

const from_storage = JSON.parse( in_storage );
console.log( from_storage ); // [ { "elem": {} } ]
<input id="my-input">

因此,每次从StorageArea中检索对象时,您实际上都需要从文档中检索元素。

为此,您可以同时使用可以传递给JSON.parse( string, reviver )的reviver函数和可以传递给JSON.stringify( object, replacer ) replacer ,这样就不必保存空白对象,则在字符串化时只保存Element的id,而不是仅检索此字符串,而是在解析时直接获得Element。

// used in JSON.parse
function reviver( key, value ) {
  if( key === "elem" ) {
    return document.getElementById( value );
  }
  return value;
}
// used in JSON.stringify
function replacer( key, value ) {
  if( key === "elem" ) {
    return value.id;
  }
  return value
}

// StackSnippets don't allow localStorage
// so let's make a fake one, already populated
const localStorage = {
  keys: `[
    {"elem":"x1split_input","key":null},
    {"elem":"x2split_input","key":81},
    {"elem":"x16split_input","key":16},
    {"elem":"respawn_input","key":82}
  ]`,
  setItem(key, val) {
    this[key] = val;
    console.log( 'saving', val );
  }
};
const keyboardMap = {81:'foo', 16:'bar', 82:'bla'};

btn.onclick = e => {
const inputs = localStorage.keys ? JSON.parse(localStorage.keys, reviver) : [
  // your initial object, not used in this demo
]

for (let obj of inputs) {
  obj.elem.value = keyboardMap[obj.key];
  obj.elem.onkeyup = (key) => {
    obj.key = key.keyCode;
    obj.elem.value = keyboardMap[obj.key];
    localStorage.setItem("keys", JSON.stringify(inputs, replacer))
  }
}
console.log(localStorage.keys)

}
<button id="btn">retrieve from (fake) localStorage</button><br>
<input id="x1split_input"><br>
<input id="x2split_input"><br>
<input id="x16split_input"><br>
<input id="respawn_input"><br>