跳到主要内容

通过我们的可选 JavaScript 插件让 Bootstrap 生动起来。了解每个插件、我们的数据和编程 API 选项,以及更多内容。

单独引入或整体编译

插件可以单独包含(使用 Bootstrap 的单独 js/dist/*.js),或者使用 bootstrap.js 或压缩的 bootstrap.min.js 一次性全部包含(不要同时包含两者)。

如果你使用打包工具(Webpack、Parcel、Vite……),你可以使用 /js/dist/*.js 文件,这些文件已经准备好 UMD。

与 JavaScript 框架的使用

虽然 Bootstrap CSS 可以与任何框架一起使用,但是 Bootstrap JavaScript 并不完全兼容像 React、Vue 和 Angular 这样的 JavaScript 框架,这些框架假设对 DOM 有完全的了解。Bootstrap 和框架都可能尝试修改同一个 DOM 元素,从而导致像下拉菜单卡在“打开”位置这样的错误。

对于使用这种类型框架的人来说,更好的替代方案是使用特定于框架的包 而不是 Bootstrap 的 JavaScript。以下是一些最受欢迎的选项:

将 Bootstrap 作为模块使用

自己试试! 从 twbs/examples 仓库 下载用于将 Bootstrap 作为 ES 模块使用的源代码和工作示例。

我们提供了一个构建为ESM(bootstrap.esm.js和bootstrap.esm.min.js)的Bootstrap版本,这使你可以在浏览器中将Bootstrap作为模块使用,前提是你的目标浏览器支持它。

<script type="module">
  import { Toast } from 'bootstrap.esm.min.js'

Array.from(document.querySelectorAll('.toast')) .forEach(toastNode => new Toast(toastNode)) </script>

与 JS 打包工具相比,在浏览器中使用 ESM 需要你使用完整的路径和文件名,而不是模块名。在浏览器中了解更多关于 JS 模块的信息。 这就是为什么我们在上面使用 'bootstrap.esm.min.js' 而不是 'bootstrap' 的原因。然而,这由于我们的 Popper 依赖而变得更加复杂,它像这样将 Popper 导入我们的 JavaScript:

import * as Popper from "@popperjs/core"

如果你按原样尝试,你会在控制台看到如下错误:

Uncaught TypeError: Failed to resolve module specifier "@popperjs/core". Relative references must start with either "/", "./", or "../".

要解决这个问题,你可以使用 importmap 将任意模块名称解析为完整路径。如果你的 目标浏览器 不支持 importmap,你将需要使用 es-module-shims 项目。以下是 Bootstrap 和 Popper 的使用方法:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
    <title>Hello, modularity!</title>
  </head>
  <body>
    <h1>Hello, modularity!</h1>
    <button id="popoverButton" type="button" class="btn btn-primary btn-lg" data-bs-toggle="popover" title="ESM in Browser" data-bs-content="Bang!">Custom popover</button>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">async</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://cdn.jsdelivr.net/npm/es-module-shims@1/dist/es-module-shims.min.js<span class="token punctuation">"</span></span> <span class="token attr-name">crossorigin</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>anonymous<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>importmap<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token punctuation">{</span>
  <span class="token string-property property">"imports"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token string-property property">"@popperjs/core"</span><span class="token operator">:</span> <span class="token string">"https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/esm/popper.min.js"</span><span class="token punctuation">,</span>
    <span class="token string-property property">"bootstrap"</span><span class="token operator">:</span> <span class="token string">"https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.esm.min.js"</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>module<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
  <span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> bootstrap <span class="token keyword">from</span> <span class="token string">'bootstrap'</span>

  <span class="token keyword">new</span> <span class="token class-name">bootstrap<span class="token punctuation">.</span>Popover</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'popoverButton'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>

</body> </html>

依赖

一些插件和 CSS 组件依赖于其他插件。如果你单独包含插件,请确保在文档中检查这些依赖关系。

我们的下拉菜单、弹出框和工具提示也依赖于 Popper。

数据属性

几乎所有的 Bootstrap 插件都可以仅通过 HTML 使用数据属性启用和配置(这是我们首选的使用 JavaScript 功能的方式)。请确保 在单个元素上只使用一组数据属性(例如,不能通过同一个按钮触发 tooltip 和 modal)。

由于选项可以通过数据属性或 JavaScript 传递,你可以将选项名称附加到 data-bs-,就像在 data-bs-animation="{value}" 中一样。确保在通过数据属性传递选项时,将选项名称的大小写类型从“camelCase”更改为“kebab-case”。例如,使用 data-bs-custom-class="beautifier" 而不是 data-bs-customClass="beautifier"。

从 Bootstrap 5.2.0 开始,所有组件都支持一个 实验性的保留数据属性 data-bs-config,它可以用作存放简单组件配置的 JSON 字符串。当一个元素同时拥有 data-bs-config='{"delay":0, "title":123}' 和 data-bs-title="456" 属性时,最终的 title 值将会是 456,且单独的数据属性将覆盖 data-bs-config 上给定的值。此外,现有的数据属性也能够存放如 data-bs-delay='{"show":0,"hide":150}' 的 JSON 值。

最终的配置对象是data-bs-config、data-bs-和js object合并的结果,其中最新提供的键值会覆盖其他键值。

选择器

出于性能原因,我们使用原生的 querySelector 和 querySelectorAll 方法查询 DOM 元素,因此你必须使用有效选择器。如果你使用像 collapse:Example 这样的特殊选择器,请确保对它们进行转义。

事件

Bootstrap 为大多数插件的独特操作提供自定义事件。通常,这些事件有不定式和过去分词形式 —— 不定式(例如 show)在事件开始时触发,而过去分词形式(例如 shown)在操作完成时触发。

所有不定事件都提供 preventDefault() 功能。这提供了在动作开始之前停止其执行的能力。从事件处理程序中返回 false 也会自动调用 preventDefault()。

const myModal = document.querySelector('#myModal')

myModal.addEventListener('show.bs.modal', event => { return event.preventDefault() // stops modal from being shown })

编程 API

所有构造函数都接受一个可选的 options 对象或不传参数(此时插件将以其默认行为初始化):

const myModalEl = document.querySelector('#myModal')
const modal = new bootstrap.Modal(myModalEl) // initialized with defaults

const configObject = { keyboard: false } const modal1 = new bootstrap.Modal(myModalEl, configObject) // initialized with no keyboard

如果你想获取一个特定的插件实例,每个插件都会提供一个 getInstance 方法。例如,直接从一个元素中检索实例:

bootstrap.Popover.getInstance(myPopoverEl)

如果实例未在请求的元素上初始化,则此方法将返回null。

或者,可以使用 getOrCreateInstance 来获取与 DOM 元素关联的实例,或者在尚未初始化的情况下创建一个新的实例。

bootstrap.Popover.getOrCreateInstance(myPopoverEl, configObject)

如果实例未被初始化,它可能会接受并使用作为第二个参数的可选配置对象。

构造函数中的 CSS 选择器

除了getInstance和getOrCreateInstance方法外,所有插件构造函数都可以接受一个 DOM 元素或一个有效的CSS 选择器作为第一个参数。插件元素通过querySelector方法找到,因为我们的插件只支持单个元素。

const modal = new bootstrap.Modal('#myModal')
const dropdown = new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
const offcanvas = bootstrap.Offcanvas.getInstance('#myOffcanvas')
const alert = bootstrap.Alert.getOrCreateInstance('#myAlert')

异步函数和过渡

所有编程 API 方法都是 异步的,并会在过渡开始后立即返回给调用者,但 在其结束之前。为了在过渡完成后执行某个操作,你可以监听相应的事件。

const myCollapseEl = document.querySelector('#myCollapse')

myCollapseEl.addEventListener('shown.bs.collapse', event => { // Action to execute once the collapsible area is expanded })

此外,对正在过渡的组件的调用方法将被忽略。

const myCarouselEl = document.querySelector('#myCarousel')
const carousel = bootstrap.Carousel.getInstance(myCarouselEl) // Retrieve a Carousel instance

myCarouselEl.addEventListener('slid.bs.carousel', event => { carousel.to('2') // Will slide to the slide 2 as soon as the transition to slide 1 is finished })

carousel.to('1') // Will start sliding to the slide 1 and returns to the caller carousel.to('2') // !! Will be ignored, as the transition to the slide 1 is not finished !!

dispose 方法

虽然使用…似乎是正确的 dispose 方法之后立即 hide(),这将导致错误的结果。以下是问题使用的示例:

const myModal = document.querySelector('#myModal')
myModal.hide() // it is asynchronous

myModal.addEventListener('shown.bs.hidden', event => { myModal.dispose() })

默认设置

你可以通过修改插件的Constructor.Default对象来更改插件的默认设置:

// changes default for the modal plugin’s `keyboard` option to false
bootstrap.Modal.Default.keyboard = false

方法和属性

每个 Bootstrap 插件都提供以下方法和静态属性。

方法描述
dispose销毁元素的模态框。(移除DOM元素上的存储数据)
getInstance静态方法,允许你获取与DOM元素关联的模态实例。
getOrCreateInstance静态方法,允许你获取与DOM元素关联的模态实例,如果未初始化,则创建一个新的模态实例。
静态属性描述
NAME返回插件名称。(例子:bootstrap.Tooltip.NAME)
VERSION可以通过插件构造函数的 VERSION 属性访问每个 Bootstrap 插件的版本。(例子:bootstrap.Tooltip.VERSION)

消毒剂

如果配置为这样做,我们的工具提示和弹出框组件能够在页面上呈现任意 HTML。为了防止跨站脚本 (XSS) 攻击,这些组件在呈现在页面之前会使用我们内置的内容清理器对所有接受 HTML 的选项进行清理。内容清理默认是启用的。

默认允许的标签和属性如下。任何未明确允许的标签或属性在清理过程中将被移除:

const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i

export const DefaultAllowlist = { // Global attributes allowed on any supplied element below. '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], a: ['target', 'href', 'title', 'rel'], area: [], b: [], br: [], col: [], code: [], dd: [], div: [], dl: [], dt: [], em: [], hr: [], h1: [], h2: [], h3: [], h4: [], h5: [], h6: [], i: [], img: ['src', 'srcset', 'alt', 'title', 'width', 'height'], li: [], ol: [], p: [], pre: [], s: [], small: [], span: [], sub: [], sup: [], strong: [], u: [], ul: [] }

使用这些高级选项时请谨慎。有关更多信息,请参阅 OWASP 跨站脚本攻击防护备忘单。仅因禁用或修改内容清理而导致的漏洞不属于 Bootstrap 安全模型的范围。

你可以向此默认 allowList 添加新值:

const myDefaultAllowList = bootstrap.Tooltip.Default.allowList

// To allow table elements myDefaultAllowList.table = []

// To allow td elements and data-bs-option attributes on td elements myDefaultAllowList.td = ['data-bs-option']

// You can push your custom regex to validate your attributes. // Be careful about your regular expressions being too lax const myCustomRegex = /^data-my-app-[\w-]+/ myDefaultAllowList['*'].push(myCustomRegex)

你也可以用专门的库替换我们的消毒器,例如 DOMPurify:

const yourTooltipEl = document.querySelector('#yourTooltip')
const tooltip = new bootstrap.Tooltip(yourTooltipEl, {
  sanitizeFn(content) {
    return DOMPurify.sanitize(content)
  }
})

可选择使用 jQuery

在 Bootstrap 5 中你不需要 jQuery,但仍然可以将我们的组件与 jQuery 一起使用。如果 Bootstrap 检测到 jQuery 在 window 对象,它会把我们所有的组件添加到 jQuery 的插件系统中。这使你能够执行以下操作:

// to enable tooltips with the default configuration
$('[data-bs-toggle="tooltip"]').tooltip()

// to initialize tooltips with given configuration $('[data-bs-toggle="tooltip"]').tooltip({ boundary: 'clippingParents', customClass: 'myClass' })

// to trigger the show method $('#myTooltip').tooltip('show')

我们的其他组件也是如此。

无冲突

有时候有必要将 Bootstrap 插件与其他 UI 框架一起使用。在这些情况下,命名空间冲突有时可能会发生。如果发生这种情况,你可以在希望恢复其值的插件上调用 .noConflict。

const bootstrapButton = $.fn.button.noConflict() // return $.fn.button to previously assigned value
$.fn.bootstrapBtn = bootstrapButton // give $().bootstrapBtn the Bootstrap functionality

Bootstrap 官方不支持像 Prototype 或 jQuery UI 这样的第三方 JavaScript 库。尽管存在 .noConflict 和命名空间事件,仍可能存在需要你自行修复的兼容性问题。

jQuery 事件

如果 Bootstrap 会检测到 jQuery jQuery 存在于 window 对象而且没有 data-bs-no-jquery 属性已设置 <body>. 如果找到 jQuery,Bootstrap 将借助 jQuery 的事件系统触发事件。因此,如果你想监听 Bootstrap 的事件,你必须使用 jQuery 方法(.on, .one) 而不是 addEventListener.

$('#myTab a').on('shown.bs.tab', () => {
  // do something...
})

已禁用 JavaScript

Bootstrap 的插件在 JavaScript 被禁用时没有特殊的回退方案。如果你在意这种情况下的用户体验,可以使用 <noscript> 向你的用户解释情况(以及如何重新启用 JavaScript),和/或添加你自己的自定义回退方案。