Skip to main content Skip to docs navigation

JavaScript

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

单独或编译

🌐 Individual or compiled

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

🌐 Plugins can be included individually (using Bootstrap’s individual js/dist/*.js), or all at once using bootstrap.js or the minified bootstrap.min.js (don’t include both).

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

🌐 If you use a bundler (Webpack, Parcel, Vite…), you can use /js/dist/*.js files which are UMD ready.

与 JavaScript 框架一起使用

🌐 Usage with JavaScript frameworks

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

🌐 While the Bootstrap CSS can be used with any framework, the Bootstrap JavaScript is not fully compatible with JavaScript frameworks like React, Vue, and Angular which assume full knowledge of the DOM. Both Bootstrap and the framework may attempt to mutate the same DOM element, resulting in bugs like dropdowns that are stuck in the “open” position.

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

🌐 A better alternative for those using this type of frameworks is to use a framework-specific package instead of the Bootstrap JavaScript. Here are some of the most popular options:

使用 Bootstrap 作为模块

🌐 Using Bootstrap as a module

自己试试!twbs/examples 仓库 下载源码和使用 Bootstrap 作为 ES 模块的演示。你也可以 在 StackBlitz 打开示例

我们提供了一个构建为 ESMbootstrap.esm.jsbootstrap.esm.min.js)的 Bootstrap 版本,这使你可以在浏览器中将 Bootstrap 作为模块使用,如果你的目标浏览器支持它

🌐 We provide a version of Bootstrap built as ESM (bootstrap.esm.js and bootstrap.esm.min.js) which allows you to use Bootstrap as a module in the browser, if your targeted browsers support it.

<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:

🌐 Compared to JS bundlers, using ESM in the browser requires you to use the full path and filename instead of the module name. Read more about JS modules in the browser. That’s why we use 'bootstrap.esm.min.js' instead of 'bootstrap' above. However, this is further complicated by our Popper dependency, which imports Popper into our JavaScript like so:

import * as Popper from "@popperjs/core"

如果你直接尝试此操作,控制台中会显示如下错误:

🌐 If you try this as-is, you’ll see an error in the console like the following:

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

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

🌐 To fix this, you can use an importmap to resolve the arbitrary module names to complete paths. If your targeted browsers do not support importmap, you’ll need to use the es-module-shims project. Here’s how it works for Bootstrap and 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" data-bs-content="Bang!">Custom popover</button>

    <script async src="https://cdn.jsdelivr.net/npm/es-module-shims@1/dist/es-module-shims.min.js" crossorigin="anonymous"></script>
    <script type="importmap">
    {
      "imports": {
        "@popperjs/core": "https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/esm/popper.min.js",
        "bootstrap": "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.esm.min.js"
      }
    }
    </script>
    <script type="module">
      import * as bootstrap from 'bootstrap'

      new bootstrap.Popover(document.getElementById('popoverButton'))
    </script>
  </body>
</html>

依赖

🌐 Dependencies

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

🌐 Some plugins and CSS components depend on other plugins. If you include plugins individually, make sure to check for these dependencies in the docs.

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

🌐 Our dropdowns, popovers, and tooltips also depend on Popper.

数据属性

🌐 Data attributes

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

🌐 Nearly all Bootstrap plugins can be enabled and configured through HTML alone with data attributes (our preferred way of using JavaScript functionality). Be sure to only use one set of data attributes on a single element (e.g., you cannot trigger a tooltip and modal from the same button.)

As options can be passed via data attributes or JavaScript, you can append an option name to data-bs-, as in data-bs-animation="{value}". Make sure to change the case type of the option name from “camelCase” to “kebab-case” when passing the options via data attributes. For example, use data-bs-custom-class="beautifier" instead of data-bs-customClass="beautifier".

As of Bootstrap 5.2.0, all components support an experimental reserved data attribute data-bs-config that can house simple component configuration as a JSON string. When an element has data-bs-config='{"delay":0, "title":123}' and data-bs-title="456" attributes, the final title value will be 456 and the separate data attributes will override values given on data-bs-config. In addition, existing data attributes are able to house JSON values like data-bs-delay='{"show":0,"hide":150}'.

The final configuration object is the merged result of data-bs-config, data-bs-, and js object where the latest given key-value overrides the others.

选择器

🌐 Selectors

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

🌐 We use the native querySelector and querySelectorAll methods to query DOM elements for performance reasons, so you must use valid selectors. If you use special selectors like collapse:Example, be sure to escape them.

事件

🌐 Events

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

🌐 Bootstrap provides custom events for most plugins’ unique actions. Generally, these come in an infinitive and past participle form - where the infinitive (ex. show) is triggered at the start of an event, and its past participle form (ex. shown) is triggered on the completion of an action.

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

🌐 All infinitive events provide preventDefault() functionality. This provides the ability to stop the execution of an action before it starts. Returning false from an event handler will also automatically call preventDefault().

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

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

程序化 API

🌐 Programmatic API

所有构造函数都接受一个可选的选项对象或不接受任何内容(这会以其默认行为启动插件):

🌐 All constructors accept an optional options object or nothing (which initiates a plugin with its default behavior):

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 方法。例如,要直接从一个元素中获取实例:

🌐 If you’d like to get a particular plugin instance, each plugin exposes a getInstance method. For example, to retrieve an instance directly from an element:

bootstrap.Popover.getInstance(myPopoverEl)

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

🌐 This method will return null if an instance is not initiated over the requested element.

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

🌐 Alternatively, getOrCreateInstance can be used to get the instance associated with a DOM element, or create a new one in case it wasn’t initialized.

bootstrap.Popover.getOrCreateInstance(myPopoverEl, configObject)

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

🌐 In case an instance wasn’t initialized, it may accept and use an optional configuration object as second argument.

构造函数中的 CSS 选择器

🌐 CSS selectors in constructors

除了 getInstancegetOrCreateInstance 方法之外,所有插件的构造函数都可以接受一个 DOM 元素或一个有效的 CSS 选择器 作为第一个参数。插件元素是使用 querySelector 方法查找的,因为我们的插件只支持单个元素。

🌐 In addition to the getInstance and getOrCreateInstance methods, all plugin constructors can accept a DOM element or a valid CSS selector as the first argument. Plugin elements are found with the querySelector method since our plugins only support a single element.

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')

异步函数和转换

🌐 Asynchronous functions and transitions

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

🌐 All programmatic API methods are asynchronous and return to the caller once the transition is started, but before it ends. In order to execute an action once the transition is complete, you can listen to the corresponding event.

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

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

此外,对正在转换的组件的方法调用将被忽略

🌐 In addition, a method call on a transitioning component will be ignored.

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 method

虽然在 hide() 之后立即使用 dispose 方法看起来是正确的,但这会导致结果不正确。以下是一个错误使用的示例:

🌐 While it may seem correct to use the dispose method immediately after hide(), it will lead to incorrect results. Here’s an example of the problem use:

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

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

默认设置

🌐 Default settings

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

🌐 You can change the default settings for a plugin by modifying the plugin’s Constructor.Default object:

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

方法和属性

🌐 Methods and properties

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

🌐 Every Bootstrap plugin exposes the following methods and static properties.

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

Sanitizer

我们的工具提示和气泡组件如果配置为这样做,可以在页面上渲染任意 HTML。为了防止跨站脚本(XSS)攻击,这些组件在将接受 HTML 的选项渲染到页面之前,会使用我们内置的内容清理器对其进行清理。内容清理默认是启用的。

🌐 Our tooltip and popover components are able to render arbitrary HTML to the page if configured to do so. To prevent cross-site scripting (XSS) attacks, these components use our built-in content sanitizer to sanitize any options which accept HTML before they are rendered to the page. Content sanitization is enabled by default.

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

🌐 The tags and attributes allowed by default are as follows. Any tags or attributes not explicitly allowed will be removed during sanitization:

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 添加新的值:

🌐 You can add new values to this default 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

🌐 You can also replace our sanitizer with a dedicated library, for example DOMPurify:

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

可以选择使用 jQuery

🌐 Optionally using jQuery

在 Bootstrap 5 中你不需要 jQuery,但仍然可以在 jQuery 中使用我们的组件。如果 Bootstrap 在 window 对象中检测到 jQuery,它将把我们所有的组件添加到 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')

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

🌐 The same goes for our other components.

没有冲突

🌐 No conflict

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

🌐 Sometimes it is necessary to use Bootstrap plugins with other UI frameworks. In these circumstances, namespace collisions can occasionally occur. If this happens, you may call .noConflict on the plugin you wish to revert the value of.

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 和命名空间事件,可能仍然存在需要你自行解决的兼容性问题。

🌐 Bootstrap does not officially support third-party JavaScript libraries like Prototype or jQuery UI. Despite .noConflict and namespaced events, there may be compatibility problems that you need to fix on your own.

jQuery 事件

🌐 jQuery events

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

🌐 Bootstrap will detect jQuery if jQuery is present in the window object and there is no data-bs-no-jquery attribute set on <body>. If jQuery is found, Bootstrap will emit events thanks to jQuery’s event system. So if you want to listen to Bootstrap’s events, you’ll have to use the jQuery methods (.on, .one) instead of addEventListener.

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

禁用 JavaScript

🌐 Disabled JavaScript

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

🌐 Bootstrap’s plugins have no special fallback when JavaScript is disabled. If you care about the user experience in this case, use <noscript> to explain the situation (and how to re-enable JavaScript) to your users, and/or add your own custom fallbacks.