You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让ASP.NET Core foreach中每个JavaScript变量保持独立?

问题根源与解决方案

你的问题出在两个核心点上:

  1. 全局作用域冲突:循环生成的脚本里,current、endtime、myFunction等都是全局变量/函数,后面的脚本会直接覆盖前面的,导致只有最后一次循环的变量生效,而第一个元素能工作只是因为它先执行了初始渲染。
  2. 重复ID选择器失效:$('#time')这类选择器会匹配页面上第一个ID为time的元素(HTML要求ID唯一),后面的元素根本不会被选中更新。

要让每个脚本保持私有、互不干扰,可以用以下两种方案:


方案一:用IIFE创建独立作用域

通过立即执行函数表达式(IIFE)把每个循环的脚本包裹起来,让变量和函数只在当前作用域内有效,同时给每个元素绑定唯一标识(比如模型的ID)来精准定位:

@foreach(var item in Model.Items)
{
    <!-- 给每个定时器容器加唯一标识 -->
    <div class="timer-box" data-item-id="@item.Id">
        <span class="current-time"></span>
        <span class="end-time"></span>
    </div>

    <script>
        // IIFE包裹,传入当前元素容器,隔离作用域
        (function(container) {
            // 精准获取当前容器内的元素
            const currentTimeEl = container.querySelector('.current-time');
            const endTimeEl = container.querySelector('.end-time');

            // 更新当前时间的定时器
            setInterval(function() {
                let now = new Date();
                currentTimeEl.textContent = now;
            }, 1000);

            // 初始化结束时间(从模型取动态值)
            const endTime = new Date('@item.EndTime');
            endTimeEl.textContent = endTime;

            // 检查结束时间的定时器
            const checkInterval = setInterval(function() {
                const now = new Date();
                if (now > endTime) {
                    doing(container);
                }
            }, 60000);

            // 私有处理函数,仅当前作用域可用
            function doing(targetContainer) {
                // 这里写时间到后的逻辑,比如标记状态、停止定时器
                targetContainer.classList.add('timer-expired');
                clearInterval(checkInterval);
            }
        })(document.querySelector('.timer-box[data-item-id="@item.Id"]'));
    </script>
}

方案二:用类封装定时器实例

把定时器逻辑封装成类,在循环里为每个元素初始化独立实例,代码更易维护:

<!-- 先在页面头部(循环外)定义通用类 -->
<script>
    class ItemTimer {
        constructor(container, endTimeStr) {
            this.container = container;
            this.endTime = new Date(endTimeStr);
            this.currentTimeEl = container.querySelector('.current-time');
            this.endTimeEl = container.querySelector('.end-time');
            this.init();
        }

        init() {
            // 初始化显示结束时间
            this.endTimeEl.textContent = this.endTime;
            // 启动时间更新
            this.startTimeUpdate();
            // 启动结束检查
            this.startEndCheck();
        }

        startTimeUpdate() {
            this.timeInterval = setInterval(() => {
                this.currentTimeEl.textContent = new Date();
            }, 1000);
        }

        startEndCheck() {
            this.checkInterval = setInterval(() => {
                if (new Date() > this.endTime) {
                    this.handleExpire();
                }
            }, 60000);
        }

        handleExpire() {
            // 时间到期后的处理逻辑
            this.container.classList.add('expired');
            // 清理定时器避免内存泄漏
            clearInterval(this.timeInterval);
            clearInterval(this.checkInterval);
        }
    }
</script>

<!-- 循环内初始化实例 -->
@foreach(var item in Model.Items)
{
    <div class="timer-box" data-item-id="@item.Id">
        <span class="current-time"></span>
        <span class="end-time"></span>
    </div>

    <script>
        // 每个元素对应一个独立实例,作用域完全隔离
        new ItemTimer(
            document.querySelector('.timer-box[data-item-id="@item.Id"]'),
            '@item.EndTime'
        );
    </script>
}

关键注意事项

  • 永远不要在循环里生成重复ID:HTML规范要求ID唯一,改用类+data-*属性定位元素更可靠。
  • 及时清理定时器:时间到期后记得用clearInterval停止定时器,避免不必要的性能消耗和内存泄漏。

内容的提问来源于stack exchange,提问作者Mohamed Yousef Khairlden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:36:31