如何使用聚合物3 PWA入门模板将状态公开给localStorage

时间:2018-11-13 18:14:56

标签: typescript polymer local-storage web-component progressive-web-apps

我正在使用从此处获取的Polymer 3 PWA入门包模板: https://github.com/Polymer/pwa-starter-kit/tree/template-typescript

我现在想按照文档中所述将状态放入localStorage。所以我要添加localstorage.ts文件

export const saveState = (state) => {
    let stringifiedState = JSON.stringify(state);
    localStorage.setItem('__wtt_store__', stringifiedState);
  }

export const loadState = () => {
    try {
        let json = localStorage.getItem('__wtt_store__') || '{}';
        let state = JSON.parse(json);
        console.log("local storage state:"+state.counter.clicks);

        if (state) {
        return state;
        } else {
        return undefined;  // To use the defaults in the reducers
        }
    } catch { 
        console.log("local storage error");
        return undefined;
    }
  }

并从模板更改了store.ts文件:

export const store = createStore(
  state => state as Reducer<RootState, RootAction>,
  loadState(),  // --------- LINE ADDED -----------------
  devCompose(
    lazyReducerEnhancer(combineReducers),
    applyMiddleware(thunk as ThunkMiddleware<RootState, RootAction>))
);

// Initially loaded reducers.
store.addReducers({
  app
});

// ---------  ADDED -----------------
store.subscribe(() => {
  saveState(store.getState());
});

控制台日志告诉我状态被写入localStorage并在刷新浏览器后加载。但是在重新加载后,组件的初始数据值又恢复为初始值,而不是已保存的localStorage的值?

在Web组件初始化期间使用localStorage的数据需要添加什么?我只是试图将“计数器”示例从PWA模板my-view2.ts保存到localStorage。但是没有成功。

需要执行什么操作才能将PWA模板的my-view2.ts中的计数器数据写入localStorage,然后重新加载以返回状态?我的解决方案无法按照手册中的标准程序进行操作。

1 个答案:

答案 0 :(得分:0)

我找到了以下解决方案。

根本原因: 每次收到商店更新时都会调用saveState(store.getState());。在应用程序启动模板中,仅加载了应用程序的减速器。在应用初始化和延迟加载期间不会加载counter元素的reducer。因此,从上一次会话到localStore的所有存储值现在都将被新的saveState函数覆盖,且仅包含应用商店数据。在这种情况下,用空数据覆盖先前保存的计数器数据。一旦加载了计数器元素并初始化了reducer,这将导致空数据。

解决方案: 在对localStore进行初始加载期间,我将上次会话中的原始完整localState保存在这样的变量中:

export let initialLocalState:any={};
export const loadState = () => {
    try {
        let json = localStorage.getItem('__wtt_store__') || '{}';
        let state = JSON.parse(json);
        //console.log("load local app storage state:"+state.counter.clicks);

        if (state) {
            initialLocalState=state;
            //console.log("Original: "+JSON.stringify(initialLocalState))
            return state;
        } else {
            return undefined;  // To use the defaults in the reducers
        }
    } catch { 
        console.log("local storage error");
        return undefined;
    }
  }

现在,为了避免用早期调用saveState覆盖完整的数据(其中可能不会初始化所有数据),在保存之前,我将全部内容合并回存储中:

export const saveState = (state) => {
    if (state==null) return;

    //ensure that we merge it with the full initial local state received during app start and store creation
    //fill up the last session state with lazy new states
    var merged = Object.assign({}, initialLocalState, state);

    let stringifiedState = JSON.stringify(merged);
    //console.log("Saving: "+stringifiedState);
    localStorage.setItem('__wtt_store__', stringifiedState);
  }

最后,我向counter.ts Web组件添加了一个操作,以从localStorage提取初始数据

// load initial data from localStore, if available
store.dispatch(loadfavorite());

此解决方案可帮助我通过延迟加载组件和化简器来保持PWA入门工具包组件的建议结构,并提供一种使上次会话中的localStorage数据完全可用的方法。