# Nuxt.js 集成 Bootstrap 5 完整方案

URL: https://caijiao.org/posts/45
Source: docs/posts/45.md
Description: 本文档详细介绍如何在 Nuxt.js 项目中集成 Bootstrap 5，包括主题定制、SCSS 变量覆盖、JS 组件使用等内容。

本文档详细介绍如何在 Nuxt.js 项目中集成 Bootstrap 5，包括主题定制、[CSS](/css/) / SCSS 变量覆盖、JS 组件使用等内容。

## 一、项目环境检查

### 当前项目依赖

| 依赖 | 版本 | 用途 |
|------|------|------|
| bootstrap | ^5.3.8 | Bootstrap 核心库 |
| sass | 1.70.0 | SCSS 预处理器 |
| nuxt | ^4.2.1 | Nuxt.js 框架 |

## 二、基础集成配置

### 1. 安装依赖

如果项目中尚未安装 Bootstrap 和 Sass，可以通过以下命令安装：

```bash
# 使用 npm
npm install bootstrap sass

# 使用 yarn
yarn add bootstrap sass

# 使用 pnpm
pnpm add bootstrap sass
```

### 2. 配置全局 CSS

在 `nuxt.config.ts` 中配置全局 SCSS 文件：

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
  css: ['~/assets/sass/style.scss'],
  // 其他配置...
})
```

### 3. 创建 Bootstrap 主样式文件

在 `app/assets/sass/` 目录下创建 `style.scss` 文件，并导入 Bootstrap SCSS 模块：

```scss
// style.scss

// Bootstrap 核心导入栈
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";

// 在这里可以覆盖 Bootstrap 变量
// 例如：$primary: #0074d9;

// 继续导入其他 Bootstrap 模块
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/root";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/type";
@import "bootstrap/scss/images";
@import "bootstrap/scss/containers";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/tables";
@import "bootstrap/scss/forms";
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/transitions";
@import "bootstrap/scss/dropdown";
@import "bootstrap/scss/button-group";
@import "bootstrap/scss/nav";
@import "bootstrap/scss/navbar";
@import "bootstrap/scss/card";
@import "bootstrap/scss/accordion";
@import "bootstrap/scss/breadcrumb";
@import "bootstrap/scss/pagination";
@import "bootstrap/scss/badge";
@import "bootstrap/scss/alert";
@import "bootstrap/scss/progress";
@import "bootstrap/scss/list-group";
@import "bootstrap/scss/close";
@import "bootstrap/scss/toasts";
@import "bootstrap/scss/modal";
@import "bootstrap/scss/tooltip";
@import "bootstrap/scss/popover";
@import "bootstrap/scss/carousel";
@import "bootstrap/scss/spinners";
@import "bootstrap/scss/offcanvas";
@import "bootstrap/scss/placeholders";
@import "bootstrap/scss/helpers";
@import "bootstrap/scss/utilities/api";
```

## 三、主题定制

### 1. 覆盖 Bootstrap 变量

在 `style.scss` 文件中，在导入 `bootstrap/scss/variables` 之后，可以覆盖任何 Bootstrap 变量来自定义主题：

```scss
// 覆盖主题颜色
$primary: #0074d9;
$danger: #dc3545;
$secondary: #6c757d;
$success: #198754;
$warning: #ffc107;
$info: #0dcaf0;
$light: #f8f9fa;
$dark: #212529;

// 自定义主题颜色映射
$theme-colors: (
    "primary": $primary,
    "danger": $danger,
    "secondary": $secondary,
    "success": $success,
    "warning": $warning,
    "info": $info,
    "light": $light,
    "dark": $dark
);

// 移除不需要的颜色
$theme-colors: map-remove($theme-colors, "info", "light", "dark");
```

### 2. 自定义排版

```scss
// 自定义字体
$font-family-sans-serif: "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;

// 自定义字体大小
$font-size-base: 1rem; // 16px
$font-size-lg: 1.25rem;
$font-size-sm: 0.875rem;
```

### 3. 自定义间距

```scss
// 自定义间距变量
$spacer: 1rem;
$spacers: (
  0: 0,
  1: $spacer * 0.25,
  2: $spacer * 0.5,
  3: $spacer,
  4: $spacer * 1.5,
  5: $spacer * 3,
  6: $spacer * 4,
  7: $spacer * 5
);
```

## 四、Bootstrap JS 组件集成

### 1. 创建 Bootstrap 客户端插件

在 `app/plugins/` 目录下创建 `bootstrap.client.js` 文件：

```javascript
// bootstrap.client.js
import Modal from "bootstrap/js/dist/modal";
import Collapse from "bootstrap/js/dist/collapse";
import Dropdown from "bootstrap/js/dist/dropdown";
import Tooltip from "bootstrap/js/dist/tooltip";
import Popover from "bootstrap/js/dist/popover";

// 可以根据需要导入其他 Bootstrap JS 组件
// import Carousel from "bootstrap/js/dist/carousel";
// import Alert from "bootstrap/js/dist/alert";
// import Toast from "bootstrap/js/dist/toast";

// 导出插件
export default defineNuxtPlugin(() => {
  return {
    provide: {
      bs: {
        Modal,
        Collapse,
        Dropdown,
        Tooltip,
        Popover,
        // Carousel,
        // Alert,
        // Toast
      },
    },
  };
});
```

### 2. 在组件中使用 JS 组件

#### 使用 v-bind:ref 和 onMounted

```vue
<template>
  <div>
    <!-- 按钮触发模态框 -->
    <button type="button" class="btn btn-primary" id="exampleModalToggle" @click="showModal">
      打开模态框
    </button>

    <!-- 模态框 -->
    <div ref="modalRef" class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel">模态框标题</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            模态框内容
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
            <button type="button" class="btn btn-primary">保存更改</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>


```

#### 使用工具类组件

```vue
<template>
  <div>
    <!-- 按钮组 -->
    <div class="btn-group" role="group" aria-label="Basic mixed styles example">
      <button type="button" class="btn btn-danger">Danger</button>
      <button type="button" class="btn btn-warning">Warning</button>
      <button type="button" class="btn btn-success">Success</button>
    </div>

    <!-- 卡片 -->
    <div class="card" style="width: 18rem;">
      <img src="..." class="card-img-top" alt="...">
      <div class="card-body">
        <h5 class="card-title">Card title</h5>
        <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
        <a href="#" class="btn btn-primary">Go somewhere</a>
      </div>
    </div>
  </div>
</template>
```

## 五、响应式设计

Bootstrap 内置了强大的响应式设计系统，可以通过断点类来控制不同屏幕尺寸下的元素显示：

```vue
<template>
  <div>
    <!-- 响应式布局 -->
    <div class="container">
      <div class="row">
        <!-- 在移动设备上占满宽度，在平板上占6列，在桌面设备上占4列 -->
        <div class="col-12 col-md-6 col-lg-4">
          <!-- 内容 -->
        </div>
        <div class="col-12 col-md-6 col-lg-4">
          <!-- 内容 -->
        </div>
        <div class="col-12 col-md-6 col-lg-4">
          <!-- 内容 -->
        </div>
      </div>
    </div>

    <!-- 响应式显示/隐藏 -->
    <div class="d-none d-md-block">
      <!-- 仅在中等及以上屏幕显示 -->
    </div>
    <div class="d-block d-sm-none">
      <!-- 仅在移动设备显示 -->
    </div>
  </div>
</template>
```

## 六、最佳实践

### 1. 按需导入组件

在 `bootstrap.client.js` 中，只导入项目中实际需要的 Bootstrap JS 组件，以减小打包体积：

```javascript
// 只导入需要的组件
import Modal from "bootstrap/js/dist/modal";
import Collapse from "bootstrap/js/dist/collapse";
// 不需要的组件不要导入
// import Carousel from "bootstrap/js/dist/carousel";
```

### 2. 使用自定义主题

通过覆盖 Bootstrap 变量来创建符合项目需求的自定义主题，而不是直接修改 Bootstrap 源文件：

```scss
// 正确：覆盖变量
$primary: #0074d9;
$border-radius: 8px;

// 错误：直接修改组件样式
.btn {
  border-radius: 8px !important;
}
```

### 3. 避免过度使用 !important

尽量通过正确的 CSS 选择器优先级来覆盖样式，避免过度使用 `!important`：

```scss
// 正确：使用更具体的选择器
.my-custom-button {
  border-radius: 8px;
}

// 错误：过度使用 !important
.btn {
  border-radius: 8px !important;
}
```

### 4. 使用组合式 API

在 Nuxt 3 中，推荐使用组合式 API 来管理 Bootstrap 组件的生命周期：

```vue

```

### 5. 结合 Nuxt 特性

将 Bootstrap 与 Nuxt 的特性结合使用，如布局系统、路由等：

```vue
<!-- 在布局组件中使用 Bootstrap 导航 -->
<template>
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container">
      
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarNav">
        <ul class="navbar-nav">
          <li class="nav-item">
            
          </li>
          <li class="nav-item">
            
          </li>
          <li class="nav-item">
            
          </li>
          <li class="nav-item">
            
          </li>
        </ul>
      </div>
    </div>
  </nav>
  <main>
    <slot />
  </main>
</template>
```

## 七、常见问题与解决方案

### 1. Bootstrap JS 组件不工作

- 确保已正确创建并配置 `bootstrap.client.js` 插件
- 确保在客户端环境中使用 JS 组件（`process.client`）
- 确保组件引用（ref）正确绑定

### 2. 自定义变量不生效

- 确保变量覆盖在 `@import "bootstrap/scss/variables"` 之后
- 确保变量覆盖在其他 Bootstrap SCSS 模块导入之前
- 检查变量名称是否与 Bootstrap 定义的一致

### 3. 样式冲突

- 使用更具体的 CSS 选择器
- 考虑使用 CSS 模块或作用域样式
- 避免直接修改 Bootstrap 源文件

---

以上就是 Nuxt.js 集成 Bootstrap 5 的完整方案。通过合理配置和使用 Bootstrap，可以快速构建美观、响应式的 Web 应用。
