
在web开发中,我们经常需要在同一页面上展示多个商品或服务,并为每个项目配备一个独立的库存倒计时器。传统的做法可能是为每个计数器复制一份脚本,并修改其html元素的id(例如,qty1、qty2等)。然而,这种方法存在明显缺陷:当脚本尝试通过document.getelementbyid('qty')获取元素时,它只会匹配到页面上的第一个id为qty的元素,导致其他复制的计数器无法正常工作。此外,如果每个计数器需要独立的状态(例如,不同的起始库存,以及将各自的倒计时状态保存到localstorage),简单的脚本复制会变得非常复杂且难以维护。
为了克服上述问题,我们可以采用Web Components(Web组件)技术,特别是自定义元素(Custom Elements)。自定义元素允许我们创建具有自定义行为和封装性的HTML标签,从而实现高度模块化和可重用的组件。
我们将创建一个名为<stock-counter>的自定义元素,它将封装库存倒计时的所有逻辑和展示。
自定义元素通过customElements.define()方法进行注册。我们的<stock-counter>元素将继承自HTMLElement,并包含以下关键特性:
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,则使用该值
if (!Number.isNaN(value) && value !== 0) {
return value;
}
}
// 否则,从 HTML 元素的 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);
}
// 更新 HTML 元素的 quantity 属性
this.setAttribute('quantity', value);
}
}
// storageKey 属性的 getter 方法
get storageKey() {
return this.getAttribute('storage-key');
}
// 当元素被添加到文档DOM时调用
connectedCallback() {
this.count(); // 启动倒计时
}
// 核心倒计时逻辑
count = () => {
const qty = this.quantity; // 获取当前库存量
this.textContent = qty; // 更新元素显示文本
if (qty === 0) {
return; // 库存为0时停止倒计时
}
// 随机减少库存量(1到3之间)
let parts = Math.floor((Math.random() * 3) + 1);
if (parts > qty) {
parts = qty; // 确保减少量不超过当前库存
}
this.quantity -= parts; // 更新库存量(通过 setter 自动保存到 localStorage)
// 随机设置下一次倒计时的延迟时间(15到30秒之间)
const msec = Math.floor(((Math.random() * 15) + 15) * 1000);
setTimeout(this.count, msec); // 延迟后递归调用 count 方法
};
});quantity (初始库存):
storage-key (持久化键):
count()方法是实现倒计时的核心。它执行以下操作:
一旦自定义元素被定义,你就可以像使用任何其他HTML标签一样在页面中使用它。只需在HTML中插入<stock-counter>标签,并通过属性设置其初始库存和存储键。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多实例库存计数器示例</title>
<style>
body { font-family: Arial, sans-serif; display: flex; justify-content: space-around; padding: 20px; }
.product-card { border: 1px solid #ccc; padding: 15px; border-radius: 8px; text-align: center; min-width: 180px; }
.product-card h3 { margin-top: 0; }
stock-counter { font-size: 2em; font-weight: bold; color: #d9534f; }
</style>
</head>
<body>
<div class="product-card">
<h3>产品 A</h3>
<p>剩余库存: <stock-counter quantity="40" storage-key="countdown-one">40</stock-counter></p>
<button>购买</button>
</div>
<div class="product-card">
<h3>产品 B</h3>
<p>剩余库存: <stock-counter quantity="50" storage-key="countdown-two">50</stock-counter></p>
<button>购买</button>
</div>
<div class="product-card">
<h3>产品 C (无持久化)</h3>
<p>剩余库存: <stock-counter quantity="80">80</stock-counter></p>
<button>购买</button>
</div>
<script>
// 将自定义元素的 JavaScript 定义放在 HTML 结构之后,或者使用 defer/async 属性
customElements.define('stock-counter', class extends HTMLElement {
get quantity() {
if (this.storageKey !== null) {
const value = Number(localStorage.getItem(this.storageKey));
if (!Number.isNaN(value) && value !== 0) {
return value;
}
}
const value = Number(this.getAttribute('quantity'));
if (Number.isNaN(value)) {
return 0;
}
return value;
}
set quantity(value) {
if (!isNaN(value)) {
if (this.storageKey !== null) {
localStorage.setItem(this.storageKey, value);
}
this.setAttribute('quantity', value);
}
}
get storageKey() {
return this.getAttribute('storage-key');
}
connectedCallback() {
this.count();
}
count = () => {
const qty = this.quantity;
this.textContent = qty;
if (qty === 0) {
return;
}
let parts = Math.floor((Math.random() * 3) + 1);
if (parts > qty) {
parts = qty;
}
this.quantity -= parts;
const msec = Math.floor(((Math.random() * 15) + 15) * 1000);
setTimeout(this.count, msec);
};
});
</script>
</body>
</html>在上面的示例中:
通过采用Web Components的自定义元素,我们成功地创建了一个高度模块化、可重用且支持独立状态持久化的库存倒计时组件。这种方法不仅解决了在同一页面上显示多个独立计数器的问题,还大大提高了代码的可维护性和可扩展性。开发者可以轻松地在任何项目中部署这些自定义元素,只需通过HTML属性进行简单的配置,而无需编写重复的JavaScript逻辑。
以上就是使用Web Components实现多实例库存倒计时器的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号