本章概述

本章将详细介绍 Bootstrap 的各种安装方式、配置方法以及开发环境的搭建。通过本章学习,你将掌握如何在不同的项目中集成 Bootstrap,并建立高效的开发工作流。

安装方式

1. CDN 引入(推荐入门)

CDN 是最简单快速的使用方式,适合快速原型开发和学习。

基本 CDN 引入

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bootstrap CDN 示例</title>
    
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <h1 class="text-primary">Hello Bootstrap!</h1>
        <button class="btn btn-success">成功按钮</button>
    </div>
    
    <!-- Bootstrap JavaScript -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
</body>
</html>

分离式 JavaScript 引入

如果你需要单独控制 Popper.js,可以使用分离式引入:

<!-- Popper.js (必须在 Bootstrap JS 之前) -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>

<!-- Bootstrap JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.min.js" integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+" crossorigin="anonymous"></script>

国内 CDN 选择

<!-- 使用 BootCDN -->
<link href="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.3.2/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/bootstrap/5.3.2/js/bootstrap.bundle.min.js"></script>

<!-- 使用 UNPKG -->
<link href="https://unpkg.com/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://unpkg.com/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>

<!-- 使用 cdnjs -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.bundle.min.js"></script>

2. 包管理器安装

npm 安装

# 安装最新版本
npm install bootstrap

# 安装指定版本
npm install bootstrap@5.3.2

# 同时安装 Popper.js(如果需要单独使用)
npm install @popperjs/core

在项目中使用:

// 导入 CSS
import 'bootstrap/dist/css/bootstrap.min.css';

// 导入 JavaScript
import 'bootstrap/dist/js/bootstrap.bundle.min.js';

// 或者按需导入
import { Modal, Tooltip } from 'bootstrap';

Yarn 安装

# 使用 Yarn 安装
yarn add bootstrap

# 安装指定版本
yarn add bootstrap@5.3.2

pnpm 安装

# 使用 pnpm 安装
pnpm add bootstrap

# 安装指定版本
pnpm add bootstrap@5.3.2

3. 下载源码

编译版本下载

Bootstrap 官网 下载编译好的版本:

bootstrap-5.3.2-dist/
├── css/
│   ├── bootstrap.css
│   ├── bootstrap.css.map
│   ├── bootstrap.min.css
│   ├── bootstrap.min.css.map
│   ├── bootstrap-grid.css
│   ├── bootstrap-grid.css.map
│   ├── bootstrap-grid.min.css
│   ├── bootstrap-grid.min.css.map
│   ├── bootstrap-reboot.css
│   ├── bootstrap-reboot.css.map
│   ├── bootstrap-reboot.min.css
│   ├── bootstrap-reboot.min.css.map
│   ├── bootstrap-utilities.css
│   ├── bootstrap-utilities.css.map
│   ├── bootstrap-utilities.min.css
│   └── bootstrap-utilities.min.css.map
└── js/
    ├── bootstrap.bundle.js
    ├── bootstrap.bundle.js.map
    ├── bootstrap.bundle.min.js
    ├── bootstrap.bundle.min.js.map
    ├── bootstrap.esm.js
    ├── bootstrap.esm.js.map
    ├── bootstrap.esm.min.js
    ├── bootstrap.esm.min.js.map
    ├── bootstrap.js
    ├── bootstrap.js.map
    ├── bootstrap.min.js
    └── bootstrap.min.js.map

源码版本下载

下载源码进行自定义编译:

# 克隆 GitHub 仓库
git clone https://github.com/twbs/bootstrap.git
cd bootstrap

# 安装依赖
npm install

# 编译源码
npm run dist

项目结构配置

1. 基础项目结构

my-bootstrap-project/
├── index.html
├── css/
│   ├── bootstrap.min.css
│   └── custom.css
├── js/
│   ├── bootstrap.bundle.min.js
│   └── main.js
├── images/
└── assets/

基础 HTML 模板

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="网站描述">
    <meta name="author" content="作者名称">
    <title>Bootstrap 项目</title>
    
    <!-- Bootstrap CSS -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    
    <!-- 自定义 CSS -->
    <link href="css/custom.css" rel="stylesheet">
    
    <!-- Favicon -->
    <link rel="icon" type="image/x-icon" href="assets/favicon.ico">
</head>
<body>
    <!-- 导航栏 -->
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
            <a class="navbar-brand" href="#">我的网站</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item">
                        <a class="nav-link active" href="#">首页</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">关于</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">联系</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
    
    <!-- 主要内容 -->
    <main class="container my-5">
        <div class="row">
            <div class="col-lg-8">
                <h1>欢迎来到我的网站</h1>
                <p class="lead">这是一个使用 Bootstrap 构建的示例页面。</p>
            </div>
            <div class="col-lg-4">
                <div class="card">
                    <div class="card-body">
                        <h5 class="card-title">侧边栏</h5>
                        <p class="card-text">这里是侧边栏内容。</p>
                    </div>
                </div>
            </div>
        </div>
    </main>
    
    <!-- 页脚 -->
    <footer class="bg-dark text-white text-center py-3">
        <div class="container">
            <p>&copy; 2023 我的网站. 保留所有权利.</p>
        </div>
    </footer>
    
    <!-- Bootstrap JavaScript -->
    <script src="js/bootstrap.bundle.min.js"></script>
    
    <!-- 自定义 JavaScript -->
    <script src="js/main.js"></script>
</body>
</html>

2. 现代前端项目结构

Vite + Bootstrap 项目

# 创建 Vite 项目
npm create vite@latest my-bootstrap-app -- --template vanilla
cd my-bootstrap-app

# 安装 Bootstrap
npm install bootstrap @popperjs/core

# 安装 Sass(用于自定义)
npm install -D sass

项目结构:

my-bootstrap-app/
├── index.html
├── package.json
├── vite.config.js
├── src/
│   ├── main.js
│   ├── style.scss
│   └── components/
└── public/

vite.config.js 配置

import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
  root: path.resolve(__dirname, 'src'),
  build: {
    outDir: '../dist'
  },
  server: {
    port: 8080
  },
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "bootstrap/scss/functions"; @import "bootstrap/scss/variables";`
      }
    }
  }
});

main.js 入口文件

// 导入 Bootstrap CSS
import 'bootstrap/dist/css/bootstrap.min.css';

// 导入自定义样式
import './style.scss';

// 导入 Bootstrap JavaScript
import 'bootstrap/dist/js/bootstrap.bundle.min.js';

// 或者按需导入
// import { Modal, Tooltip, Popover } from 'bootstrap';

// 初始化应用
document.addEventListener('DOMContentLoaded', function() {
    console.log('Bootstrap 应用已加载');
    
    // 初始化工具提示
    const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
    const tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
        return new bootstrap.Tooltip(tooltipTriggerEl);
    });
});

自定义样式文件 (style.scss)

// 导入 Bootstrap 函数和变量
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";

// 自定义变量
$primary: #007bff;
$secondary: #6c757d;
$success: #28a745;
$info: #17a2b8;
$warning: #ffc107;
$danger: #dc3545;
$light: #f8f9fa;
$dark: #343a40;

// 自定义字体
$font-family-sans-serif: "Helvetica Neue", Arial, "Noto Sans", sans-serif;

// 导入 Bootstrap
@import "bootstrap/scss/bootstrap";

// 自定义样式
.custom-header {
    background: linear-gradient(135deg, $primary, $info);
    color: white;
    padding: 2rem 0;
}

.custom-card {
    border: none;
    box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
    transition: box-shadow 0.15s ease-in-out;
    
    &:hover {
        box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
    }
}

3. Webpack 配置

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'js/[name].[contenthash].js',
        clean: true
    },
    module: {
        rules: [
            {
                test: /\.(scss|css)$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    {
                        loader: 'sass-loader',
                        options: {
                            implementation: require('sass')
                        }
                    }
                ]
            },
            {
                test: /\.(png|svg|jpg|jpeg|gif)$/i,
                type: 'asset/resource',
                generator: {
                    filename: 'images/[name].[hash][ext]'
                }
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/i,
                type: 'asset/resource',
                generator: {
                    filename: 'fonts/[name].[hash][ext]'
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename: 'index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].[contenthash].css'
        })
    ],
    devServer: {
        static: './dist',
        port: 8080,
        open: true
    }
};

构建工具集成

1. Gulp 集成

gulpfile.js

const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const cleanCSS = require('gulp-clean-css');
const uglify = require('gulp-uglify');
const concat = require('gulp-concat');
const browserSync = require('browser-sync').create();
const del = require('del');

// 路径配置
const paths = {
    scss: {
        src: 'src/scss/**/*.scss',
        dest: 'dist/css/'
    },
    js: {
        src: 'src/js/**/*.js',
        dest: 'dist/js/'
    },
    html: {
        src: 'src/**/*.html',
        dest: 'dist/'
    },
    bootstrap: {
        css: 'node_modules/bootstrap/dist/css/bootstrap.min.css',
        js: 'node_modules/bootstrap/dist/js/bootstrap.bundle.min.js'
    }
};

// 清理任务
function clean() {
    return del(['dist']);
}

// 编译 SCSS
function styles() {
    return gulp.src(paths.scss.src)
        .pipe(sass().on('error', sass.logError))
        .pipe(cleanCSS())
        .pipe(gulp.dest(paths.scss.dest))
        .pipe(browserSync.stream());
}

// 处理 JavaScript
function scripts() {
    return gulp.src([paths.bootstrap.js, paths.js.src])
        .pipe(concat('main.min.js'))
        .pipe(uglify())
        .pipe(gulp.dest(paths.js.dest));
}

// 复制 HTML
function html() {
    return gulp.src(paths.html.src)
        .pipe(gulp.dest(paths.html.dest));
}

// 复制 Bootstrap CSS
function bootstrapCSS() {
    return gulp.src(paths.bootstrap.css)
        .pipe(gulp.dest(paths.scss.dest));
}

// 开发服务器
function serve() {
    browserSync.init({
        server: {
            baseDir: './dist'
        }
    });
    
    gulp.watch(paths.scss.src, styles);
    gulp.watch(paths.js.src, scripts);
    gulp.watch(paths.html.src, html).on('change', browserSync.reload);
}

// 监听任务
function watch() {
    gulp.watch(paths.scss.src, styles);
    gulp.watch(paths.js.src, scripts);
    gulp.watch(paths.html.src, html);
}

// 构建任务
const build = gulp.series(clean, gulp.parallel(styles, scripts, html, bootstrapCSS));
const dev = gulp.series(build, serve);

// 导出任务
exports.clean = clean;
exports.styles = styles;
exports.scripts = scripts;
exports.html = html;
exports.watch = watch;
exports.serve = serve;
exports.build = build;
exports.dev = dev;
exports.default = build;

package.json 脚本

{
  "name": "bootstrap-gulp-project",
  "version": "1.0.0",
  "scripts": {
    "build": "gulp build",
    "dev": "gulp dev",
    "watch": "gulp watch",
    "clean": "gulp clean"
  },
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-sass": "^5.1.0",
    "gulp-clean-css": "^4.3.0",
    "gulp-uglify": "^3.0.2",
    "gulp-concat": "^2.6.1",
    "browser-sync": "^2.29.3",
    "del": "^7.1.0",
    "sass": "^1.69.5"
  },
  "dependencies": {
    "bootstrap": "^5.3.2"
  }
}

2. Parcel 集成

项目结构

my-parcel-app/
├── src/
│   ├── index.html
│   ├── index.js
│   └── styles.scss
├── package.json
└── .parcelrc

.parcelrc 配置

{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.{ts,tsx}": ["@parcel/transformer-typescript-tsc"]
  }
}

package.json

{
  "name": "bootstrap-parcel-app",
  "version": "1.0.0",
  "scripts": {
    "start": "parcel src/index.html",
    "build": "parcel build src/index.html",
    "clean": "rm -rf dist .parcel-cache"
  },
  "devDependencies": {
    "parcel": "^2.10.0",
    "sass": "^1.69.5"
  },
  "dependencies": {
    "bootstrap": "^5.3.2"
  }
}

自定义配置

1. Sass 变量自定义

创建自定义变量文件

// custom-variables.scss

// 颜色自定义
$primary: #6f42c1;
$secondary: #fd7e14;
$success: #20c997;
$info: #0dcaf0;
$warning: #ffc107;
$danger: #e74c3c;
$light: #f8f9fa;
$dark: #212529;

// 字体自定义
$font-family-sans-serif: "Inter", "Helvetica Neue", Arial, sans-serif;
$font-family-monospace: "JetBrains Mono", "Fira Code", monospace;

// 字体大小
$font-size-base: 1rem;
$font-size-sm: $font-size-base * 0.875;
$font-size-lg: $font-size-base * 1.25;

// 间距
$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
);

// 边框半径
$border-radius: 0.5rem;
$border-radius-sm: 0.25rem;
$border-radius-lg: 0.75rem;
$border-radius-xl: 1rem;

// 断点自定义
$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px,
  xxl: 1400px,
  xxxl: 1600px  // 添加超大断点
);

// 容器最大宽度
$container-max-widths: (
  sm: 540px,
  md: 720px,
  lg: 960px,
  xl: 1140px,
  xxl: 1320px,
  xxxl: 1500px
);

// 组件自定义
$navbar-padding-y: 1rem;
$navbar-padding-x: 1.5rem;

$card-border-radius: $border-radius-lg;
$card-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);

$btn-border-radius: $border-radius;
$btn-border-radius-sm: $border-radius-sm;
$btn-border-radius-lg: $border-radius-lg;

主样式文件

// main.scss

// 1. 导入自定义变量
@import "custom-variables";

// 2. 导入 Bootstrap 函数
@import "bootstrap/scss/functions";

// 3. 导入 Bootstrap 变量(会使用我们的自定义变量)
@import "bootstrap/scss/variables";

// 4. 导入 Bootstrap mixins
@import "bootstrap/scss/mixins";

// 5. 导入 Bootstrap 组件(可选择性导入)
@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";

// 6. 自定义样式
@import "custom-components";

自定义组件样式

// custom-components.scss

// 自定义按钮样式
.btn-gradient {
  background: linear-gradient(45deg, $primary, $info);
  border: none;
  color: white;
  
  &:hover {
    background: linear-gradient(45deg, darken($primary, 10%), darken($info, 10%));
    color: white;
  }
}

// 自定义卡片样式
.card-hover {
  transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
  
  &:hover {
    transform: translateY(-5px);
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
  }
}

// 自定义导航栏
.navbar-custom {
  background: linear-gradient(135deg, $primary, $secondary);
  
  .navbar-brand,
  .nav-link {
    color: white !important;
    
    &:hover {
      color: rgba(255, 255, 255, 0.8) !important;
    }
  }
}

// 自定义表单
.form-floating-custom {
  .form-control {
    border-radius: $border-radius-lg;
    border: 2px solid transparent;
    background-color: $light;
    
    &:focus {
      border-color: $primary;
      box-shadow: 0 0 0 0.2rem rgba($primary, 0.25);
    }
  }
  
  label {
    color: $secondary;
  }
}

// 响应式工具类
@include media-breakpoint-up(xxxl) {
  .container-xxxl {
    max-width: map-get($container-max-widths, xxxl);
  }
}

// 自定义动画
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.animate-fade-in-up {
  animation: fadeInUp 0.6s ease-out;
}

// 暗色主题支持
@media (prefers-color-scheme: dark) {
  :root {
    --bs-body-bg: #{$dark};
    --bs-body-color: #{$light};
  }
  
  .card {
    background-color: lighten($dark, 10%);
    border-color: lighten($dark, 20%);
  }
}

2. JavaScript 模块化配置

按需导入 Bootstrap 组件

// bootstrap-modules.js

// 只导入需要的组件
import { Modal } from 'bootstrap/js/dist/modal';
import { Dropdown } from 'bootstrap/js/dist/dropdown';
import { Tooltip } from 'bootstrap/js/dist/tooltip';
import { Popover } from 'bootstrap/js/dist/popover';
import { Toast } from 'bootstrap/js/dist/toast';
import { Carousel } from 'bootstrap/js/dist/carousel';
import { Collapse } from 'bootstrap/js/dist/collapse';
import { Offcanvas } from 'bootstrap/js/dist/offcanvas';

// 创建 Bootstrap 管理器
class BootstrapManager {
    constructor() {
        this.components = {
            Modal,
            Dropdown,
            Tooltip,
            Popover,
            Toast,
            Carousel,
            Collapse,
            Offcanvas
        };
        
        this.instances = new Map();
    }
    
    // 初始化所有组件
    init() {
        this.initTooltips();
        this.initPopovers();
        this.initToasts();
        this.initCarousels();
    }
    
    // 初始化工具提示
    initTooltips() {
        const tooltipTriggerList = [].slice.call(
            document.querySelectorAll('[data-bs-toggle="tooltip"]')
        );
        
        tooltipTriggerList.forEach(tooltipTriggerEl => {
            const tooltip = new Tooltip(tooltipTriggerEl);
            this.instances.set(tooltipTriggerEl, tooltip);
        });
    }
    
    // 初始化弹出框
    initPopovers() {
        const popoverTriggerList = [].slice.call(
            document.querySelectorAll('[data-bs-toggle="popover"]')
        );
        
        popoverTriggerList.forEach(popoverTriggerEl => {
            const popover = new Popover(popoverTriggerEl);
            this.instances.set(popoverTriggerEl, popover);
        });
    }
    
    // 初始化提示框
    initToasts() {
        const toastElList = [].slice.call(
            document.querySelectorAll('.toast')
        );
        
        toastElList.forEach(toastEl => {
            const toast = new Toast(toastEl);
            this.instances.set(toastEl, toast);
        });
    }
    
    // 初始化轮播图
    initCarousels() {
        const carouselElList = [].slice.call(
            document.querySelectorAll('.carousel')
        );
        
        carouselElList.forEach(carouselEl => {
            const carousel = new Carousel(carouselEl, {
                interval: 5000,
                wrap: true
            });
            this.instances.set(carouselEl, carousel);
        });
    }
    
    // 创建模态框
    createModal(element, options = {}) {
        const modal = new Modal(element, options);
        this.instances.set(element, modal);
        return modal;
    }
    
    // 显示提示框
    showToast(message, type = 'info') {
        const toastHtml = `
            <div class="toast align-items-center text-white bg-${type} border-0" role="alert">
                <div class="d-flex">
                    <div class="toast-body">
                        ${message}
                    </div>
                    <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
                </div>
            </div>
        `;
        
        const toastContainer = document.querySelector('.toast-container') || this.createToastContainer();
        toastContainer.insertAdjacentHTML('beforeend', toastHtml);
        
        const toastElement = toastContainer.lastElementChild;
        const toast = new Toast(toastElement);
        toast.show();
        
        // 自动清理
        toastElement.addEventListener('hidden.bs.toast', () => {
            toastElement.remove();
        });
        
        return toast;
    }
    
    // 创建提示框容器
    createToastContainer() {
        const container = document.createElement('div');
        container.className = 'toast-container position-fixed bottom-0 end-0 p-3';
        document.body.appendChild(container);
        return container;
    }
    
    // 销毁组件实例
    dispose(element) {
        const instance = this.instances.get(element);
        if (instance) {
            instance.dispose();
            this.instances.delete(element);
        }
    }
    
    // 销毁所有实例
    disposeAll() {
        this.instances.forEach((instance, element) => {
            instance.dispose();
        });
        this.instances.clear();
    }
}

// 导出单例
export default new BootstrapManager();

使用示例

// main.js
import BootstrapManager from './bootstrap-modules.js';

// DOM 加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
    // 初始化 Bootstrap 组件
    BootstrapManager.init();
    
    // 示例:显示欢迎提示
    BootstrapManager.showToast('欢迎使用我们的网站!', 'success');
    
    // 示例:创建动态模态框
    const createModalBtn = document.getElementById('createModal');
    if (createModalBtn) {
        createModalBtn.addEventListener('click', () => {
            const modalHtml = `
                <div class="modal fade" tabindex="-1">
                    <div class="modal-dialog">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">动态模态框</h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                            </div>
                            <div class="modal-body">
                                <p>这是一个动态创建的模态框。</p>
                            </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>
            `;
            
            document.body.insertAdjacentHTML('beforeend', modalHtml);
            const modalElement = document.body.lastElementChild;
            
            const modal = BootstrapManager.createModal(modalElement);
            modal.show();
            
            // 模态框隐藏后清理
            modalElement.addEventListener('hidden.bs.modal', () => {
                BootstrapManager.dispose(modalElement);
                modalElement.remove();
            });
        });
    }
});

// 页面卸载时清理
window.addEventListener('beforeunload', () => {
    BootstrapManager.disposeAll();
});

开发工具配置

1. VS Code 配置

.vscode/settings.json

{
  "emmet.includeLanguages": {
    "javascript": "html"
  },
  "emmet.triggerExpansionOnTab": true,
  "css.validate": false,
  "scss.validate": false,
  "less.validate": false,
  "files.associations": {
    "*.scss": "scss"
  },
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll": true
  },
  "liveServer.settings.port": 3000,
  "liveServer.settings.root": "/dist"
}

推荐扩展

// .vscode/extensions.json
{
  "recommendations": [
    "ritwickdey.liveserver",
    "bradlc.vscode-tailwindcss",
    "syler.sass-indented",
    "ms-vscode.vscode-typescript-next",
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "formulahendry.auto-rename-tag",
    "christian-kohler.path-intellisense",
    "zignd.html-css-class-completion"
  ]
}

2. 代码格式化配置

.prettierrc

{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "bracketSpacing": true,
  "arrowParens": "avoid",
  "endOfLine": "lf",
  "htmlWhitespaceSensitivity": "css",
  "overrides": [
    {
      "files": "*.scss",
      "options": {
        "singleQuote": false
      }
    }
  ]
}

.eslintrc.js

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  extends: [
    'eslint:recommended'
  ],
  parserOptions: {
    ecmaVersion: 12,
    sourceType: 'module'
  },
  rules: {
    'indent': ['error', 2],
    'linebreak-style': ['error', 'unix'],
    'quotes': ['error', 'single'],
    'semi': ['error', 'always'],
    'no-unused-vars': 'warn',
    'no-console': 'warn'
  },
  globals: {
    'bootstrap': 'readonly'
  }
};

3. Git 配置

.gitignore

# 依赖
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# 构建输出
dist/
build/
.parcel-cache/

# 环境变量
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# 操作系统
.DS_Store
Thumbs.db

# 日志
logs
*.log

# 临时文件
*.tmp
*.temp

# 缓存
.cache/
.sass-cache/

# 测试覆盖率
coverage/
.nyc_output/

性能优化

1. 按需加载

只加载需要的 CSS

// 只导入需要的 Bootstrap 组件
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/mixins";

// 基础样式
@import "bootstrap/scss/root";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/type";
@import "bootstrap/scss/containers";
@import "bootstrap/scss/grid";

// 只导入使用的组件
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/nav";
@import "bootstrap/scss/navbar";
@import "bootstrap/scss/card";
@import "bootstrap/scss/modal";

// 工具类(可选)
@import "bootstrap/scss/utilities/api";

动态导入 JavaScript

// 动态导入组件
async function loadModal() {
    const { Modal } = await import('bootstrap/js/dist/modal');
    return Modal;
}

// 使用示例
document.getElementById('openModal').addEventListener('click', async () => {
    const Modal = await loadModal();
    const modal = new Modal(document.getElementById('myModal'));
    modal.show();
});

2. CDN 优化

<!-- 使用 preload 预加载关键资源 -->
<link rel="preload" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"></noscript>

<!-- 使用 defer 延迟加载 JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" defer></script>

3. 构建优化

Webpack 优化配置

// webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    mode: 'production',
    optimization: {
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    compress: {
                        drop_console: true,
                    },
                },
            }),
            new CssMinimizerPlugin(),
        ],
        splitChunks: {
            chunks: 'all',
            cacheGroups: {
                bootstrap: {
                    test: /[\\/]node_modules[\\/]bootstrap[\\/]/,
                    name: 'bootstrap',
                    chunks: 'all',
                },
            },
        },
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/[name].[contenthash].css',
        }),
    ],
};

故障排除

1. 常见问题

样式不生效

<!-- 检查 CSS 引入顺序 -->
<link href="bootstrap.min.css" rel="stylesheet">
<link href="custom.css" rel="stylesheet"> <!-- 自定义样式应该在 Bootstrap 之后 -->

JavaScript 组件不工作

// 确保 DOM 加载完成
document.addEventListener('DOMContentLoaded', function() {
    // 初始化 Bootstrap 组件
    const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
    const tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
        return new bootstrap.Tooltip(tooltipTriggerEl);
    });
});

响应式不工作

<!-- 确保包含 viewport meta 标签 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">

2. 调试技巧

使用浏览器开发工具

// 检查 Bootstrap 是否正确加载
console.log(typeof bootstrap !== 'undefined' ? 'Bootstrap 已加载' : 'Bootstrap 未加载');

// 检查组件实例
const modal = bootstrap.Modal.getInstance(document.getElementById('myModal'));
console.log(modal);

CSS 调试

/* 临时边框调试 */
* {
    outline: 1px solid red !important;
}

/* 网格调试 */
.container,
.container-fluid {
    outline: 2px solid blue;
}

.row {
    outline: 2px solid green;
}

[class*="col-"] {
    outline: 2px solid orange;
}

练习题

基础练习

  1. CDN 集成

    • 创建一个使用 CDN 的 Bootstrap 页面
    • 包含导航栏、轮播图和卡片组件
    • 确保所有交互功能正常工作
  2. 包管理器安装

    • 使用 npm 创建一个新项目
    • 安装 Bootstrap 和必要的构建工具
    • 配置 Sass 编译
  3. 自定义主题

    • 创建自定义的颜色方案
    • 修改字体和间距
    • 编译生成自定义的 Bootstrap CSS

进阶练习

  1. Webpack 集成

    • 配置 Webpack 构建流程
    • 实现代码分割和懒加载
    • 优化构建性能
  2. 组件按需加载

    • 实现 JavaScript 组件的动态导入
    • 创建组件管理器
    • 优化页面加载性能
  3. 开发环境配置

    • 配置热重载开发服务器
    • 设置代码格式化和检查
    • 创建自动化构建流程

本章总结

通过本章学习,我们掌握了:

  1. 多种安装方式:CDN、包管理器、源码下载等不同的集成方法

  2. 项目结构配置:从基础项目到现代前端工具链的完整配置

  3. 构建工具集成:Vite、Webpack、Gulp、Parcel 等工具的配置方法

  4. 自定义配置:Sass 变量自定义和 JavaScript 模块化配置

  5. 开发工具配置:IDE 配置、代码格式化、版本控制等开发环境优化

  6. 性能优化:按需加载、CDN 优化、构建优化等性能提升技巧

  7. 故障排除:常见问题的解决方法和调试技巧

正确的安装配置是使用 Bootstrap 的基础,选择合适的集成方式和配置开发环境将大大提高开发效率。在下一章中,我们将深入学习 Bootstrap 的网格系统和响应式布局。