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

如何在单页面中实现多个Modal实例正常运行?

团队页面个人简介模态弹窗修复方案

问题背景

我正在开发一个带个人简介模态弹窗的团队页面,采用Hugo框架搭配Babel JS,未使用Bootstrap。现有代码可生成团队卡片及对应弹窗,但功能无法正常工作,需要调整。

现有代码

主页面HTML

<div class="team-ui">
{{ with .Params.executive_team }}
   {{ range . }}
      {{ partial "components/modalTeammate.html" . }}
   {{ end }}
{{ end }}
</div>

{{ with .Params.executive_team }}
   {{ range . }}
      {{ partial "components/modalTeammateBio.html" . }}
   {{ end }}
{{ end }}

modalTeammate.html(团队卡片组件)

<div class="teammate-card trigger" data-id="#myBio-{{ .modal_id }}" data-toggle="modal" data-target="myBio-{{ .modal_id }}" id="trigger">
    <img src="{{ if .img_overwrite }}/uploads/headshot-{{ .img_overwrite }}.png{{ else }}/uploads/headshot-{{ .name }}.png{{ end }}" alt="{{ .name }} | {{ .job_title }}" loading="lazy" class="teammate-img">
    <p class="teammate-name">{{ .name }}</p>
    <p class="teammate-jobtitle">{{ .job_title }}</p>
</div>

modalTeammateBio.html(弹窗组件)

<div class="modal myBio-{{ .modal_id }}" tabindex="-1" role="dialog" aria-hidden="true" id="myBio-{{ .modal_id }}">
    <div class="modal-content">
        <div class="modal-body">
            <div class="bio-box">
                <div class="bio-box-sidebar">
                    <img src="{{ if .img_overwrite }}/uploads/headshot-{{ .img_overwrite }}.png{{ else }}/uploads/headshot-{{ .name }}.png{{ end }}" alt="{{ .name }} | {{ .job_title }}" loading="lazy" class="teammate-img">
                    <p class="teammate-name">{{ .name }}</p>
                    <p class="teammate-jobtitle">{{ if .job_title_long }}{{ .job_title_long }}{{ else }}{{ .job_title }}{{ end }}</p>
                </div>
                <div class="bio-box-content">
                {{ with .bio }}
                    {{ range . }}
                    <p class="has-margin-bottom-half">{{ .p }}</p>
                    {{ end }}
                {{ end }}
                </div>
                <button class="modal-close is-large" aria-label="close"></button>
            </div>
        </div>
    </div>
</div> 

当前JS代码

var modal = document.querySelector(".modal");
var trigger = document.querySelector(".trigger");
var videoID = trigger.getAttribute('data-id');
var closeButton = document.querySelector(".modal-close");

// YouTube Player API Reference
var tag = document.createElement('script');

tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

var player;
function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        height: '390',
        width: '640',
        videoId: videoID
    });
}

function toggleModal(e) {
    if (!modal.classList.contains("is-active")) {
        modal.classList.add("is-active");
        player.playVideo()
    }
    else {
        modal.classList.remove("is-active");
        player.pauseVideo()
    }
}

function windowOnClick(e) {
    if (e.target === modal) {
        toggleModal();
    }
}

trigger.addEventListener("click", toggleModal);
closeButton.addEventListener("click", toggleModal);
window.addEventListener("click", windowOnClick);

参考实现代码

<a href="#" data-id="{{.Get "youtube"}}" class="button is-warning trigger" data-toggle="modal" id="trigger">Watch the Video</a>
<div class="modal" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-content">
        <div class="modal-body" id="player">
            Content
        </div>
    </div>
    <button class="modal-close is-large" aria-label="close"></button>
</div>

<script src="/js/modal.js"></script>

修复调整要点

1. 移除无关代码

需求是个人简介弹窗,无需YouTube播放器,直接删除所有与YT.Player、onYouTubeIframeAPIReady相关的代码及videoID变量。

2. 修复重复ID问题

modalTeammate.html中的id="trigger"会因循环生成重复ID,直接删除该属性,仅保留class即可:

<div class="teammate-card trigger" data-id="#myBio-{{ .modal_id }}" data-toggle="modal" data-target="myBio-{{ .modal_id }}">
    <!-- 原有内容不变 -->
</div>

3. 重构JS适配多弹窗

当前JS仅获取第一个触发器和弹窗,需遍历所有触发器,为每个元素绑定对应事件:

// 获取所有触发器
const triggers = document.querySelectorAll('.trigger');

triggers.forEach(trigger => {
    // 匹配对应弹窗
    const modalId = trigger.getAttribute('data-id');
    const modal = document.querySelector(modalId);
    const closeButton = modal.querySelector('.modal-close');

    // 弹窗切换逻辑
    function toggleModal() {
        modal.classList.toggle('is-active');
        // 更新无障碍属性
        modal.setAttribute('aria-hidden', !modal.classList.contains('is-active'));
    }

    // 绑定点击事件
    trigger.addEventListener('click', toggleModal);
    closeButton.addEventListener('click', toggleModal);
    
    // 点击弹窗背景关闭
    modal.addEventListener('click', (e) => {
        if (e.target === modal) toggleModal();
    });
});

4. 添加基础CSS样式

确保弹窗默认隐藏,激活时显示:

.modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.5);
    display: none;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}

.modal.is-active {
    display: flex;
}

.modal-content {
    background-color: #fff;
    padding: 2rem;
    border-radius: 4px;
    max-width: 800px;
    width: 90%;
    position: relative;
    overflow-y: auto;
    max-height: 90vh;
}

.modal-close {
    position: absolute;
    top: 1rem;
    right: 1rem;
    border: none;
    background: transparent;
    font-size: 1.5rem;
    cursor: pointer;
}

内容的提问来源于stack exchange,提问作者Muksim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:20:39