浮生一梦

Bootstrap Modal 组件报错

|
阅读: 0
| #问题 #前端

参考资料

没找到解决方法,随便看看

异常

之前在实现 Hexo 前面的搜索功能,有使用到 Bootstrap 的模态框

<!-- 模态窗口 -->
    <div class="modal" id="searchModal"  tabindex="-1" aria-modal="true" role="dialog">
        <div class="modal-dialog modal-lg" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">搜索</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <input type="text" class="form-control" id="searchInput" placeholder="Keyword">
                    <div class="search-content" id="searchResult"></div>
                </div>
            </div>
        </div>
    </div>

可能是之前没注意,后续在控制台发现一个报错,虽然不影响使用,但显示台看着有点碍眼,解决记录下

image.png

触发这个异常的原因是我在模态窗显示的时候,点击关闭按钮隐藏模态窗
image.png

而问题产生来自于 aria-hidden 属性

aria-hidden 属性

aria-hidden 属性不熟悉,查了下资料,具体可参考 MDN

aria-hidden 属性用于指示辅助技术(如屏幕阅读器、读屏软件),主要是给残障人士使用的,当你给一个元素添加 aria-hidden 属性的时候,该元素会对「读屏软件」隐藏

对于正常人而言,元素的隐藏状态基于其是否被渲染。
通常是通过 CSS 的 display 属性设置为 none 来决定是否可见

对于残障人士,使用辅助技术「读屏软件」来阅读内容,设置了 aria-hidden 属性的元素,虽然肉眼可见(对于正常人来讲),但「读屏软件」会忽略该元素。

aria-hidden 属性因为对于「读屏软件」是隐藏的,所以有这个属性的元素及其子元素都不允许获取焦点。

问题

Bootstrap 模态窗问题的警告就是来自于焦点管理
Bootstrap 的 js 默认会给模态窗容器添加上 aria-hidden=true 
image.png

由于我代码更新了,所以这里拿 Fluid 主题举例,因为 Fluid 主题也是使用的 bootstrap 的模态窗,HTML 结构有些许不同,但原理一样

可以看到模态窗下面的元素(关闭按钮)包含有 aria-hidden=true
image.png

当点击关闭按钮的时候,焦点在按钮上,而按钮在包含有 aria-hidden=true 属性的元素内,上面说到拥有 aria-hidden=true 属性的元素对于屏幕阅读器而言是隐藏的,所以这对屏幕阅读器而言,就是焦点消失了(隐藏了),从而引发了错误,也就是控制台所报告的:

有一个元素拥有焦点,而它的一个祖先元素设置了 aria-hidden。这意味着焦点被隐藏了,这违反了 WAI-ARIA 规范。

解决方法

有几种解决方法

  1. 移除 aria-hidden="true" 属性。
  2. 确保焦点元素不在 aria-hidden="true" 元素的后代中。
  3. 使用 inert 属性替代 aria-hiddeninert 属性可以防止元素获得焦点。

我这里采用方案 1

bootstrap 的模态窗口本身不写这个属性是也没用的

<!-- 模态窗口 -->
    <div class="modal" id="searchModal"  tabindex="-1" aria-modal="true" role="dialog">
        <div class="modal-dialog modal-lg" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">搜索</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <input type="text" class="form-control" id="searchInput" placeholder="Keyword">
                    <div class="search-content" id="searchResult"></div>
                </div>
            </div>
        </div>
    </div>

因为 bootstrap.min.js 还是会给自动加上的,显示模态窗和隐藏模态窗的事件处理中会动态添加

所以要么只能改动 bootstrap.min.js 代码,要么自己重写模态窗的事件处理,全看个人

改动代码

bootstrapjs 中设置该属性的行注释掉,不设置这个属性即可

image.png

重写事件处理

仅供参考使用,可能要因地制宜

function serachEvent() {
  /* 搜索相关事件 */
  var modal = document.getElementById("searchModal"); // 模态窗
  var searchBtn = document.querySelector(
    '.links-item[data-bs-toggle="modal"][data-bs-target="#searchModal"]'
  ); // 触发按钮
  var closeButton = modal.querySelector(".btn-close"); // 模态窗关闭按钮

  // 点击触发按钮时显示模态框
  searchBtn.addEventListener("click", () => {
    showModal();
  });

  // 点击关闭按钮时隐藏模态框
  closeButton.addEventListener("click", hideModal);

  // 点击模态窗外部时隐藏模态框
    modal.addEventListener("click", function (event) { 
        if (event.target.classList.contains("is-visible")) {
            hideModal();
        }
    });

  // 按下 ESC 键关闭模态窗口
  document.addEventListener("keydown", function (event) {
    if (event.key === "Escape" && modal.classList.contains("is-visible")) {
      hideModal();
    }
  });
}

// 显示模态框
function showModal() {
    var searchInput = document.getElementById("searchInput");
    body.classList.add('no-scroll')
  modal.classList.add("is-visible");
  searchInput.focus();
}

// 隐藏模态框
function hideModal() {
    body.classList.remove("no-scroll");
  modal.classList.remove("is-visible");
}
👍 0
❤️ 0
😑 0
👎 0
👀 0
:D 获取中...