首页 > 其他分享 >通过项目中的实际例子,介绍 LocalStorage 在 Angular 开发中的使用场景

通过项目中的实际例子,介绍 LocalStorage 在 Angular 开发中的使用场景

时间:2023-11-27 23:34:57浏览次数:46  
标签:存储 场景 Storage storage LocalStorage localStorage Local Angular

笔者之前在掘金社区的技术文章,介绍过自己项目组中负责开发的一款基于 Angular 的电商 SDK:

本文笔者会分享自己项目过程中,在设计这款 SDK 时使用 Web 开发领域的 LocalStorage 技术来实现的一个功能。

用户访问 Storefront 的 homepage,可以在 Language 的下拉菜单里,选择语言:

比如下图是语言切换成中文的效果:

同样还支持货币单位的切换:

客户的需求是,更改的这些设置,在关闭浏览器之后,仍然能够生效。意思是下次重新打开浏览器,Storefront homepage 仍然按照之前的设置去加载。

为此,我们团队采取的实现方式是,利用 Web 开发领域中的 LocalStorage 技术,来持久化用户指定的 Language 和货币单位的更改。

Local Storage 技术概述

Local Storage 技术是一种在Web 浏览器中用于客户端数据存储的机制。它允许 Web 应用程序在用户的本地浏览器上存储键值对形式的数据,这样用户在关闭浏览器窗口或页面后,数据仍然可以保留。这为开发者提供了一种在客户端持久保存数据的简单方式,而不必依赖于服务器。

我们在 Chrome 开发者工具 Application 面板里,可以清晰观察到这些 Key Value 键值对:

Local Storage 是Web Storage API 的一部分,与 Session Storage 不同,Local Storage 的数据在关闭浏览器后仍然存在。它使用键值对的形式存储数据,其中键和值都是字符串。该技术基于域名,即同一域名下的所有页面共享相同的 Local Storage

使用方式也非常简单直观,使用其提供的 get 和 set API 即可。

在 JavaScript 中,通过 localStorage 对象来访问和操作 Local Storage。以下是一些基本的 localStorage 操作:

存储数据:

// 存储数据
localStorage.setItem('username', 'John');

// 存储数字
localStorage.setItem('userAge', 25);

读取数据:

// 读取数据
const username = localStorage.getItem('username');
const userAge = localStorage.getItem('userAge');

删除数据:

// 删除数据
localStorage.removeItem('username');

清空所有数据:

// 清空所有数据
localStorage.clear();

我们项目组当时选择用 LocalStorage 技术来实现用户需求,也是基于了如下考虑:

  1. 持久性: 数据在浏览器关闭后仍然存在,适用于长期保存用户偏好设置等信息,比如我们项目中客户对于 Language 和货币单位的持久化需求。

  2. 容量: Local Storage 允许存储较大数量的数据(通常至少5MB),相对于 Cookie 的4KB而言,具备更大的容量,我们用来存储两个字符串值,可以说是绰绰有余。

  3. 简易性: 使用简单的键值对操作,易于理解和实现。

尽管 LocalStorage 数据存储在客户端,但是我们存储的仅仅是 Language 和货币单位,所以不存在敏感信息。

Local Storage 技术的项目实战

首先我们在 state-config.ts 文件里定义了 StorageSyncType 的枚举值:

可以看到目前我们打算支持 LocalStorage 和 SessionStorage 两种方式,方便 SDK 的 consumer 自己切换。

而 getStorage 函数用来封装获取 LocalStorage API 的行为:

export function getStorage(
  storageType: StorageSyncType,
  winRef: WindowRef
): Storage | undefined {
  let storage: Storage | undefined;

  switch (storageType) {
    case StorageSyncType.LOCAL_STORAGE: {
      storage = winRef.localStorage;
      break;
    }
    case StorageSyncType.SESSION_STORAGE: {
      storage = winRef.sessionStorage;
      break;
    }
    case StorageSyncType.NO_STORAGE: {
      storage = undefined;
      break;
    }

    default: {
      storage = winRef.sessionStorage;
    }
  }

这里 storage API 从依赖注入参数的 winReflocalStorage 或者 sessionStorage 字段里读取。
这两个字段都是全局对象 window 里的标准属性之一。

本文之前介绍的 LocalStorage API 就位于 localStorage 字段的原型链上,如下图高亮区域所示:

language 字段的 LocalStorage 读取

用户重新打开浏览器时,需要从 LocalStorage 里将存储的 language 字段值读取出来。

这个场景通过下图的 readFromStorage 函数实现:

export function readFromStorage(storage: Storage, key: string): unknown {
  if (isSsr(storage)) {
    return;
  }

  const storageValue = storage.getItem(key);
  if (!storageValue) {
    return;
  }

  return JSON.parse(storageValue);
}

逻辑很直接,首先判断是否是在 SSR 环境下,如果是就直接返回。因为按照笔者这篇文章的介绍,用户的个性化设置和私有数据页面,比如购物车,WishList 等,不应该被 Angular 服务器端渲染考虑,所以我们代码里如果 isSsr 检测函数返回 true,直接返回;否则调用 storage 的 API 即 getItem 返回浏览器 LocalStorage 里的存储值。

下面是调试器里的截图:

language 字段的 LocalStorage 的写入

当用户在 Storefront 界面上用下拉菜单更换 Language 字段值时,会调用 browser-storage.ts 里的 persistToStorage 方法:

我们可以看到这个方法里调用代码第 44 行的 setItem,将 Angular UI 上用户选定的值写入到 LocalStorage 里。

下拉菜单的实现位于 site-context-selector.component.html 文件内部。当用户切换下拉菜单值的时候,触发第 3 行 select 元素的 change 事件。

事件的处理函数主体就只有一个 active = $any($event).target.value 的赋值操作,这会触发定义在 active 属性上的 set 方法:

set 方法里调用 this.componentService.setActive(value, this.context),这个函数调用最终把执行投递到 storage.setItem(configKey, JSON.stringify(value)) 上去:

总结

在 Local Storage 出现之前,客户端数据存储主要依赖于 cookies。但是,cookies 存在许多不足,比如存储空间有限(通常只有 4KB),数据在每次 HTTP 请求时都会被发送到服务器,这会消耗更多的带宽。相比之下,Local Storage 提供了更大的存储空间(通常是 5MB),并且数据只存储在客户端,不会被发送到服务器。这使得 Local Storage 成为一种更有效的客户端数据存储方式。

本文介绍了笔者在实际 Angular 开发项目中使用 Local Storage 来持久化用户个性化选择的一个案例,希望能帮助到需要实现类似功能的开发者们。

标签:存储,场景,Storage,storage,LocalStorage,localStorage,Local,Angular
From: https://www.cnblogs.com/sap-jerry/p/17860837.html

相关文章

  • 零数科技应用入选2023全球数商大会数据要素典型应用场景优秀案例
    11月25-26日,2023全球数商大会在上海召开。本届大会以“数联全球、商通未来”为主题,上海市委副书记、市长龚正出席大会并宣布大会开幕,国家发展改革委党组成员,国家数据局党组书记、局长刘烈宏,上海市副市长陈杰致辞。2023数据交易节于11月25日同期举办,并颁布年度数据要素典型应用场景......
  • 图解Redis适用场景
    Redis以其速度而闻名。1业务数据缓存1.1通用数据缓存string,int,list,map。Redis最常见的用例是缓存对象以加速Web应用程序。此用例中,Redis将频繁请求的数据存储在内存。允许Web服务器快速返回频繁访问的数据。这减轻数据库的负载并提高应用程序RT。规模扩张时,缓存分......
  • 分析安科瑞Acrel-EIOT能源物联网平台的工作原理以及应用场景—李笑曼
    安科瑞电气股份有限公司李笑曼壹柒捌贰壹壹贰玖柒叁叁1功能Acrel-EIoT能源物联网开放平台是一套基于物联网数据中台,建立统一的上下行数据标准,为互联网用户提供能源物联网数据服务的平台。用户仅需购买安科瑞物联网传感器,选配网关,自行安装后扫码即可使用手机和电脑得到所需的行......
  • 大量索引场景下 Easysearch 和 Elasticsearch 的吞吐量差异
    最近有客户在使用Elasticsearch搜索服务时发现集群有掉节点,并且有master收集节点信息超时的日志,节点的负载也很高,不只是data节点,master和协调节点的cpu使用率都很高,看现象集群似乎遇到了性能瓶颈。查看了Hot_threads,发现大量线程被权限验证相关的类和方法占用,主要在RB......
  • 大量索引场景下 Easysearch 和 Elasticsearch 的吞吐量差异
    最近有客户在使用Elasticsearch搜索服务时发现集群有掉节点,并且有master收集节点信息超时的日志,节点的负载也很高,不只是data节点,master和协调节点的cpu使用率都很高,看现象集群似乎遇到了性能瓶颈。查看了Hot_threads,发现大量线程被权限验证相关的类和方法占用,主要在......
  • 中伟视界:AI盒子智能分析算法解决油气管道长无人场景下的人车监测问题
        在油气管道长又无人的场景下,人和车的监测问题一直是一个难题。传统的监测手段往往存在盲区和误报问题,给管道运行安全带来了一定的隐患。然而,随着人工智能技术的不断发展,利用AI盒子的智能分析算法可以有效解决这一问题。AI盒子可以通过视频监控系统实时检测管道周边的人......
  • 并发编程场景题目
    (1)发红包,100块钱,10个红包,要求第一个抢到红包的用户,得到的金额最多?解答:可以先将每个红包的金额计算出来,然后放到一个并发队列中concurrentLinkedQueue,每个用户就是一个线程,每个线程去操作并发集合,集合为空的线程就返回红包派送完了。(2)搜索引擎:公司有三种搜索引擎,每个搜索引擎的搜......
  • Angular 依赖注入领域里 optional constructor parameters 的概念介绍
    Angular依赖注入(DI)是一个强大且灵活的设计模式,它可以帮助我们更好地管理和组织我们的代码。构造函数参数的可选性(Optional)是AngularDI系统的一个重要特性。这种特性允许我们将某些服务或值作为可选依赖注入到组件或服务中,这样,如果这些服务或值不存在,我们的代码仍然可以正常工......
  • 什么是 Angular 基于 Constructor Parameter 的 Dependency Injection
    在Angular中,依赖注入(DependencyInjection,DI)是一种设计模式,用于处理如何在不同的代码部分创建和传递依赖对象。在Angular中,我们通常依赖于TypeScript的特性,如构造函数参数(constructorparameters)来执行依赖注入。构造函数参数进行依赖注入是AngularDI系统的一个重要特......
  • Angular 使用 Constructor Parameters 进行依赖注入的优缺点
    构造函数参数(ConstructorParameters)在Angular中是一种进行依赖注入(DependencyInjection)的重要方式之一。依赖注入是一种设计模式,通过该模式,一个类的依赖关系不是在类内部直接创建,而是通过外部提供这些依赖关系。在Angular中,依赖注入通过注入器(Injector)来实现,而构造函数参数是一......