如何在单页面中实现多个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
相关产品推荐
相关产品推荐

