Bootstrap 5 报 TypeError: $ is not a function 是因彻底移除 jQuery 依赖,需删除 jQuery 引入、改用原生 API 初始化组件(如 new bootstrap.Modal())、动态元素需手动初始化,并用 CSS transition 替代 jQuery 动画。
TypeError: $ is not a function 怎么办因为 Bootstrap 5 彻底删掉了 jQuery 依赖,所有 JS 组件(Modal、Dropdown、Toast 等)都重写为原生 DOM API + ES6+ 类。只要代码里还留着 $().modal('show') 或 $('.dropdown').dropdown(),浏览器就直接报这个错。
实操建议:
jquery.min.js 或 jquery.slim.js 的引入(除非其他插件强依赖)bootstrap.bundle.min.js)已正确加载,且在你的自定义脚本之前执行$('#myModal').modal('show') → new bootstrap.Modal(document.getElementById('myModal')).show()
bootstrap(小写),不是 Bootstrap 或 BS
data-bs-toggle 还能用吗?为什么动态插入的 HTML 不生效能用,但只对「页面加载时已存在的元素」自动初始化。Bootstrap 5 启动时会扫描 DOM,匹配 data-bs-toggle="modal" 这类属性并调用对应构造器 —— 这个过程只跑一次。
常见错误现象:
立即学习“前端免费学习笔记(深入)”;
innerHTML 或 insertAdjacentHTML 动态加了个带 data-bs-toggle="dropdown" 的按钮,点不动原因很简单:Bootstrap 不监听 DOM 变化,也不会劫持 innerHTML。它不提供 MutationObserver 自动补救。
实操建议:
const dropdownEl = document.querySelector('.my-dynamic-dropdown'); new bootstrap.Dropdown(dropdownEl);
data-bs-toggle,一边又 new bootstrap.Dropdown(...),否则事件监听可能重复绑定if (dropdownEl) { new bootstrap.Dropdown(dropdownEl); }
不是简单改函数名,而是整套交互范式变了。核心替换点集中在 DOM 查询、事件绑定、类名操作和动画触发上。
常见对比与注意事项:
$('.btn') → document.querySelectorAll('.btn')(返回 NodeList,不是数组,需 [...] 展开或用 forEach)$(el).on('click', handler) → el.addEventListener('click', handler)(注意:事件目标是元素本身,不是 jQuery 对象)$(el).addClass('active') → el.classList.add('active')(classList 是原生 API,支持 toggle/replace).fadeIn(),而是靠 CSS transition + 切换类,比如 el.classList.add('fade-in') 配合 .fade-in { opacity: 1; transition: opacity .15s; }
性能影响:原生操作更快,内存占用更低,但需要自己处理 IE 兼容性(Bootstrap 5 已不支持 IE)。
transition 能替代 jQuery 的 fadeIn/slideToggle
因为 Bootstrap 5 的所有过渡效果(模态框淡入、下拉菜单展开、提示框滑出)全部基于 CSS transition 和 @keyframes 实现,JS 只负责添加/移除类,不操纵内联样式或定时器。
这样做的好处:
容易踩的坑:
.fade 类默认 opacity: 0,但若没写 transition: opacity .15s,就不会有淡入效果display: none 配合 transition 无效 —— display 不支持过渡,得用 visibility + opacity 或 max-height
modal.show() 后,如果 CSS 中 .modal.fade .modal-dialog 缺少 transition,动画就变成硬切最常被忽略的一点:Bootstrap 5 的动画类(如 .fade、.show)必须和对应结构配合使用,单独加类不会触发完整行为 —— 它们只是 CSS 钩子,背后依赖 JS 控制类的增删时机。