0

0

在同一页面实现多个独立库存计数器:利用自定义元素解决状态隔离问题

霞舞

霞舞

发布时间:2025-10-07 13:55:38

|

710人浏览过

|

来源于php中文网

原创

在同一页面实现多个独立库存计数器:利用自定义元素解决状态隔离问题

本文介绍如何通过JavaScript自定义元素(Custom Elements)在同一网页上实现多个独立的动态库存计数器。针对传统方法中ID冲突和localStorage共享导致的问题,我们构建了一个可重用的组件,每个组件都能独立管理其库存数量,并支持通过localStorage进行持久化,从而解决多产品库存展示的难题。

传统库存计数器在多实例场景下的局限性

在网页中实现一个动态变化的库存计数器,通常会涉及到dom元素的更新和数据持久化。常见的做法是使用一个元素配合javascript来显示和更新数量,并通过localstorage来保存当前计数,以便页面刷新后能恢复状态。然而,当需要在同一页面上展示多个独立的库存计数器时,这种方法会遇到显著的问题:

  1. ID冲突问题: 如果多个计数器都使用相同的ID(例如id="qty"),document.getElementById()将只会获取到页面上的第一个匹配元素,导致其他计数器无法正常工作。
  2. localStorage共享问题: 如果所有计数器都使用相同的localStorage键来存储数量,它们将共享同一个库存值,一个计数器的变化会影响到所有其他计数器,无法实现独立管理。

简单地复制脚本并修改ID并不能解决localStorage共享的问题,因为每个脚本实例仍然会尝试读写同一个localStorage键,导致行为不一致。为了解决这些挑战,我们需要一种更组件化、更封装的解决方案。

引入自定义元素(Custom Elements)实现独立计数器

JavaScript的自定义元素(Custom Elements)提供了一种强大的方式来创建可重用的组件,它们拥有自己的生命周期、属性和方法,并且能够封装内部逻辑和状态。通过自定义元素,我们可以为每个库存计数器创建一个独立的实例,从而避免上述问题。

我们将创建一个名为的自定义元素。每个实例都可以独立地管理其库存数量,并可选择通过唯一的storage-key在localStorage中进行持久化。

自定义元素结构与核心逻辑

以下是定义自定义元素的完整代码:

customElements.define('stock-counter', class extends HTMLElement {
  // quantity 属性的 getter 方法
  get quantity() {
    // 检查是否设置了 storageKey 且 localStorage 中存在有效值
    if (this.storageKey !== null) {
      const value = Number(localStorage.getItem(this.storageKey));
      // 如果值是有效数字且不为0,则使用 localStorage 中的值
      if (!Number.isNaN(value) && value !== 0) {
        return value;
      }
    }

    // 否则,从元素的 quantity 属性中获取初始值
    const value = Number(this.getAttribute('quantity'));
    // 如果 quantity 属性值无效,则返回 0
    if (Number.isNaN(value)) {
      return 0;
    }
    return value;
  }

  // quantity 属性的 setter 方法
  set quantity(value) {
    if (!isNaN(value)) {
      // 如果设置了 storageKey,则将新值保存到 localStorage
      if (this.storageKey !== null) {
        localStorage.setItem(this.storageKey, value);
      }
      // 更新元素的 quantity 属性
      this.setAttribute('quantity', value);
    }
  }

  // storageKey 属性的 getter 方法
  get storageKey() {
    return this.getAttribute('storage-key');
  }

  // 当元素被添加到文档时调用
  connectedCallback() {
    this.count(); // 启动计数器
  }

  // 核心计数逻辑
  count = () => {
    const qty = this.quantity; // 获取当前数量
    this.textContent = qty; // 更新元素显示的文本内容

    if (qty === 0) {
      return; // 如果数量为0,停止计数
    }

    let parts = Math.floor((Math.random() * 3) + 1); // 随机生成减少的数量 (1-3)

    if (parts > qty) {
      parts = qty; // 如果减少量大于当前数量,则减少量等于当前数量
    }

    this.quantity -= parts; // 更新数量(通过 setter 会自动更新 localStorage 和属性)

    const msec = Math.floor(((Math.random() * 15) + 15) * 1000); // 随机生成延迟时间 (15-30秒)
    setTimeout(this.count, msec); // 在指定延迟后再次调用 count 方法
  };
});

代码解析

  1. customElements.define('stock-counter', class extends HTMLElement { ... });:

    • 这是定义自定义元素的标准方式。'stock-counter'是元素的标签名,必须包含连字符。
    • class extends HTMLElement表示我们的自定义元素继承自标准的HTMLElement接口,拥有所有HTML元素的特性。
  2. quantity 属性(getter 和 setter):

    • get quantity(): 这是获取当前库存数量的逻辑。
      • 它首先检查元素是否设置了storage-key属性。如果设置了,它会尝试从localStorage中读取对应的值。
      • 如果localStorage中的值是一个有效的非零数字,则优先使用该值。这确保了页面刷新后能恢复上次的计数状态。
      • 如果localStorage中没有有效值,或者storage-key未设置,它会回退到从元素的quantity属性(HTML中的quantity="...")获取初始值。
      • 如果quantity属性值无效(例如非数字),则默认为0。
    • set quantity(value): 这是设置库存数量的逻辑。
      • 当数量更新时,如果设置了storage-key,它会自动将新值保存到localStorage中。
      • 同时,它也会更新元素的quantity属性,确保DOM中的属性值与内部状态同步。
  3. storageKey 属性(getter):

    MakeSong
    MakeSong

    AI音乐生成,生成高质量音乐,仅需30秒的时间

    下载
    • 简单地返回元素storage-key属性的值。这个属性是可选的,用于指定localStorage的键名。
  4. connectedCallback():

    • 这是自定义元素的生命周期方法之一,当元素首次被添加到文档DOM时调用。
    • 在这里,我们调用this.count()来启动计数器逻辑。
  5. count() 方法:

    • 这是实现库存递减的核心逻辑。
    • this.textContent = qty;:将当前库存数量显示在自定义元素内部。
    • if (qty === 0) return;:当库存为0时,停止计数。
    • let parts = Math.floor((Math.random() * 3) + 1);:随机生成每次递减的数量(1到3之间)。
    • if (parts > qty) parts = qty;:确保递减的数量不会超过当前库存。
    • this.quantity -= parts;:更新库存数量。由于quantity属性有setter,这会自动触发localStorage的更新。
    • const msec = Math.floor(((Math.random() * 15) + 15) * 1000);:随机生成一个延迟时间(15到30秒之间)。
    • setTimeout(this.count, msec);:在随机延迟后递归调用count方法,实现动态递减。

如何使用自定义元素

一旦自定义元素被定义,你就可以像使用任何标准HTML标签一样在页面中使用它。


40


50


80

在上面的示例中:

  • 每个元素都将独立运行。
  • quantity属性定义了计数器的初始值。
  • storage-key属性是可选的。如果设置了,该计数器的状态将通过这个唯一的键名在localStorage中持久化。这意味着刷新页面后,带有storage-key的计数器会从上次保存的值继续计数。没有storage-key的计数器将始终从quantity属性指定的初始值开始。
  • 元素内部的文本内容(例如40中的40)会在计数器启动后被更新为当前数量。

注意事项与总结

  • 浏览器兼容性: 自定义元素是Web Components标准的一部分,现代浏览器(Chrome, Firefox, Edge, Safari)都已良好支持。对于旧版浏览器,可能需要引入Polyfill。
  • storage-key的重要性: 如果你希望某个计数器的状态在页面刷新后依然保持,务必为其设置一个全局唯一的storage-key。不同的计数器使用相同的storage-key会导致它们共享状态,再次引入传统方法的缺陷。
  • 初始值与持久化: 当一个元素被加载时,它会优先尝试从localStorage中读取由storage-key指定的值。如果localStorage中没有有效值或storage-key未设置,它才会使用quantity属性作为初始值。
  • 封装性 自定义元素将HTML结构、CSS样式(如果添加)和JavaScript行为封装在一起,提高了代码的可维护性和可重用性。

通过采用自定义元素,我们能够优雅地解决在同一页面上部署多个独立动态库存计数器的难题,为产品展示、活动倒计时等场景提供了强大而灵活的解决方案。这种组件化的方法不仅使代码更清晰,也大大提升了开发效率和用户体验。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
chrome什么意思
chrome什么意思

chrome是浏览器的意思,由Google开发的网络浏览器,它在2008年首次发布,并迅速成为全球最受欢迎的浏览器之一。本专题为大家提供chrome相关的文章、下载、课程内容,供大家免费下载体验。

827

2023.08.11

chrome无法加载插件怎么办
chrome无法加载插件怎么办

chrome无法加载插件可以通过检查插件是否已正确安装、禁用和启用插件、清除插件缓存、更新浏览器和插件、检查网络连接和尝试在隐身模式下加载插件方法解决。更多关于chrome相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

743

2023.11.06

edge是什么浏览器
edge是什么浏览器

Edge是一款由Microsoft开发的网页浏览器,是Windows 10操作系统中默认的浏览器,其目标是提供更快、更安全、更现代化的浏览器体验。本专题为大家提供edge浏览器相关的文章、下载、课程内容,供大家免费下载体验。

1409

2023.08.21

IE浏览器自动跳转EDGE如何恢复
IE浏览器自动跳转EDGE如何恢复

ie浏览器自动跳转edge的解决办法:1、更改默认浏览器设置;2、阻止edge浏览器的自动跳转;3、更改超链接的默认打开方式;4、禁用“快速网页查看器”;5、卸载edge浏览器;6、检查第三方插件或应用程序等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

381

2024.03.05

如何解决Edge打开但没有标题的问题
如何解决Edge打开但没有标题的问题

若 Microsoft Edge 浏览器打开后无标题(窗口空白或标题栏缺失),可尝试以下方法解决: 重启 Edge:关闭所有窗口,重新启动浏览器。 重置窗口布局:右击任务栏 Edge 图标 → 选择「最大化」或「还原」。 禁用扩展:进入 edge://extensions 临时关闭插件测试。 重置浏览器设置:前往 edge://settings/reset 恢复默认配置。 更新或重装 Edge:检查最新版本,或通过控制面板修复

933

2025.04.24

typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

109

2023.09.26

define的用法
define的用法

define用法:1、定义常量;2、定义函数宏:3、定义条件编译;4、定义多行宏。更多关于define的用法的内容,大家可以阅读本专题下的文章。

338

2023.10.11

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

775

2023.08.22

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

CSS教程
CSS教程

共754课时 | 24.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号