Как я могу следить за изменениями в localStorage в Angular2?

Я пытался понять, как заставить меню появляться и исчезать на основе входа в систему в предыдущем сообщении. Но я думаю, что лучше и, возможно, проще было бы задать вопрос, как я могу отслеживать изменения в локальном хранилище?

Я использую веб-токены json в локальном хранилище для своей аутентификации, я хотел бы следить за изменениями в localStorage, а затем повторно обновлять свое представление о новой информации.

Я установил свой localStorage с этим

localStorage.setItem('jwt', my_token);

То, что я хотел бы сделать, это проверить, есть ли у меня токен, если ничего не происходит, но когда происходит изменение, запускается событие. Мне бы особенно хотелось, чтобы я мог наблюдать только за определенным именованным событием, например localStorage.getItem('jwt').

Спасибо!

ИЗМЕНИТЬ:

Гюнтер указал мне правильное направление, но на случай, если кого-то это все еще смущает, вот плункер, показывающий вам, как это сделать. http://plnkr.co/edit/TiUasGdutCsll1nI6USC?p=preview


person Morgan G    schedule 14.02.2016    source источник
comment
Как вы заставили это работать с локальным хранилищем?   -  person pwborodich    schedule 09.09.2016
comment
По сути, вы не можете следить за тем, что входит в локальное хранилище, но вы можете создать наблюдаемое для любых изменений в локальном хранилище и следить за этим изменением. Итак, что вы делаете, это загружаете глобальную службу, считываете ее из локального хранилища один раз, а затем всякий раз, когда эта переменная может измениться из-за того, что я меняю свой веб-токен или что-то в этом роде, я оборачиваю эту переменную наблюдаемым и наблюдаю за изменениями в этой переменной, включая повторное обновление локального хранилища и все, что я хочу сделать с этим изменением.   -  person Morgan G    schedule 10.09.2016


Ответы (4)


Главное — использовать window.addEventListener("storage", . Хотя библиотека, вероятно, делает это правильно для angular, вот облегченная версия, которую я собрал, используя .bind(this) вместо того, чтобы копаться во внутренностях angular.

    import { Injectable, OnDestroy } from '@angular/core';
    import { Subject } from 'rxjs/Subject';
    import { share } from 'rxjs/operators';
    
    @Injectable()
    export class StorageService implements OnDestroy {
      private onSubject = new Subject<{ key: string, value: any }>();
      public changes = this.onSubject.asObservable().pipe(share());
    
      constructor() {
        this.start();
      }
    
      ngOnDestroy() {
        this.stop();
      }
    
      public getStorage() {
        let s = [];
        for (let i = 0; i < localStorage.length; i++) {
          s.push({
            key: localStorage.key(i),
            value: JSON.parse(localStorage.getItem(localStorage.key(i)))
          });
        }
        return s;
      }
    
      public store(key: string, data: any): void {
        localStorage.setItem(key, JSON.stringify(data));
        this.onSubject.next({ key: key, value: data})
      }
    
      public clear(key) {
        localStorage.removeItem(key);
        this.onSubject.next({ key: key, value: null });
      }
    
    
      private start(): void {
        window.addEventListener("storage", this.storageEventListener.bind(this));
      }
    
      private storageEventListener(event: StorageEvent) {
        if (event.storageArea == localStorage) {
          let v;
          try { v = JSON.parse(event.newValue); }
          catch (e) { v = event.newValue; }
          this.onSubject.next({ key: event.key, value: v });
        }
      }
    
      private stop(): void {
        window.removeEventListener("storage", this.storageEventListener.bind(this));
        this.onSubject.complete();
      }
    }

ЛокалСторажеТвоТабс

person Stephen    schedule 06.12.2017
comment
Спасибо за ваш ответ, но я думаю, что его нужно обновить с помощью нового стандарта ts - person MrSolarius; 15.06.2021

Используйте службу и получайте доступ к LocalStorage только через эту службу из любой точки мира.
Затем служба может предоставлять наблюдаемые объекты, которые генерируют события при изменениях, и вы можете подписаться на эти наблюдаемые объекты, чтобы получать уведомления.

person Günter Zöchbauer    schedule 14.02.2016
comment
Благодарю вас! Есть примеры такого кода? Я посмотрел на Plunker, опубликованный @MorganG, но все еще немного сбит с толку. Я хотел бы использовать localStorage для хранения настроек моего приложения, которые будут обновляться в каждом соответствующем компоненте при изменении из компонента настроек. - person Harry; 28.10.2016
comment
Вы можете попробовать такой пакет, как npmjs.com/package/ng2-local-storage (сам не пробовал). Было бы проще, если бы вы разместили новый вопрос с кодом, который демонстрирует, что вы пробовали, и объясняете, что вызывает у вас проблемы. Трудно понять, что тебе непонятно. - person Günter Zöchbauer; 28.10.2016
comment
Спасибо @GünterZöchbauer; У меня есть что-то работающее в моем приложении, если у меня будет время, я поставлю это в плункер. Неясность заключается не в вашем ответе, а в том, что я все еще изучаю реактивное программирование и пытаюсь разобраться в этом, поэтому мне было интересно, были ли уже написаны какие-либо конкретные примеры. Я понял/поддерживаю концепцию, но больше боролся с реализацией. Я буду продолжать в том же духе :) - person Harry; 28.10.2016
comment
@GünterZöchbauer, не могли бы вы помочь мне узнать, как отслеживать изменения, внесенные в локальное хранилище, на другой вкладке. поэтому данные изменяются через службу, но они находятся на другой вкладке, но мне нужно, чтобы это отражалось на текущей вкладке. case senario: - выход из вкладки должен распространяться на другие вкладки, чтобы API не возвращал 401. или продукт, добавленный в корзину на каждой вкладке, должен отображаться при оформлении заказа. - person Ashutosh Raj; 20.11.2017

Обновленная версия https://stackoverflow.com/a/47683091/3098882 с новым rxjs 6.

import { Injectable, OnDestroy } from '@angular/core';
import { Subject } from "rxjs";
import { share } from 'rxjs/operators';

@Injectable()
export class StorageService implements OnDestroy {
    private onSubject = new Subject<{ key: string, value: any }>();
    public changes = this.onSubject.asObservable().pipe(share());

    constructor() {
        this.start();
    }

    ngOnDestroy() {
        this.stop();
    }

    public getStorage() {
        let s = [];
        for (let i = 0; i < localStorage.length; i++) {
            s.push({
                key: localStorage.key(i),
                value: JSON.parse(localStorage.getItem(localStorage.key(i)))
            });
        }
        return s;
    }

    public store(key: string, data: any): void {
        localStorage.setItem(key, JSON.stringify(data));
        // the local application doesn't seem to catch changes to localStorage...
        this.onSubject.next({key: key, value: data})
    }

    public clear(key) {
        localStorage.removeItem(key);
        // the local application doesn't seem to catch changes to localStorage...
        this.onSubject.next({key: key, value: null});
    }


    private start(): void {
        window.addEventListener("storage", this.storageEventListener.bind(this));
    }

    private storageEventListener(event: StorageEvent) {
        if (event.storageArea == localStorage) {
            let v;
            try {
                v = JSON.parse(event.newValue);
            } catch (e) {
                v = event.newValue;
            }
            this.onSubject.next({key: event.key, value: v});
        }
    }

    private stop(): void {
        window.removeEventListener("storage", this.storageEventListener.bind(this));
        this.onSubject.complete();
    }
}
person jeckep    schedule 15.07.2019

Я знаю, что этот пост немного устарел, но есть библиотеки, которые могут сделать это за вас. Например, h5webstorage позволит вам рассматривать localStorage и sessionStorage как обычные объекты, а синхронизация выполняется автоматически. Даже изменения в хранилище напрямую вернутся в ваше приложение.

person SirDarquan    schedule 28.04.2016