You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask Jinja模板中Bootstrap5 Popover报错不生效问题

问题根因
  • bootstrap is not defined 报错有三个核心诱因:一是自定义初始化脚本放在了content块中,该块渲染位置早于Bootstrap JS bundle的引入位置,浏览器执行初始化代码时Bootstrap全局对象还未加载;二是page_2.jinja开头的模板继承标签语法错误,缺失左大括号,会导致模板渲染顺序异常;三是原基础模板未引入Bootstrap CSS文件,组件样式本身无法正常加载。
  • 弹出层默认常驻显示:手动编写了带show类、固定定位内联样式的Popover DOM结构,Bootstrap Popover组件会自动生成弹出层DOM,无需手动预写,手动添加的结构默认就会展示在页面上。同时原配置中data-bs-content传的是字符串nav_dropdown,Bootstrap会默认将其作为纯文本渲染,不会自动匹配对应id的DOM内容;且img标签默认不可聚焦,data-bs-trigger="focus"配置无法正常生效。
修复步骤
  • 调整基础模板结构:在head标签中补充Bootstrap CSS引入,在Bootstrap JS引入语句后新增专属的scripts块,所有页面自定义JS都放到该块中,保证Bootstrap加载完成后再执行自定义逻辑。
  • 修正子模板语法:补全page_2.jinja开头继承标签缺失的左大括号,使用标准Jinja2继承语法。
  • 移除手动编写的常驻Popover DOM结构,将自定义下拉内容存入<template>标签中,该标签内的内容默认不会渲染到页面上。
  • 调整触发元素配置:给头像img标签添加tabindex="0"属性保证元素可被聚焦,初始化Popover时开启HTML内容渲染,将content指向自定义模板的内容,固定弹出位置。
  • 将Popover初始化代码挪到基础模板预留的scripts块中。
修正后代码示例

基础模板 layout.jinja2

<!DOCTYPE html>
<html lang="en">
    <head>
        <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.png') }}">
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <!-- 补充Bootstrap CSS引入 -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
        <title>{{ title }}</title>
    </head>

    <body class="{{template}}">
        <div class="container">
            {% block content %}
            
            {% endblock %}
        </div>
        <!-- JavaScript Bundle with Popper -->
        <script 
            src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.js" 
            integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" 
            crossorigin="anonymous"></script>
        <!-- 新增自定义脚本块,放在Bootstrap加载之后 -->
        {% block scripts %}{% endblock %}
    </body>
</html>

子模板 page_2.jinja

{# 修正继承标签语法错误 #}
{% extends "layout.jinja2" %}

{% block content %}
    <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
        <div class="container-fluid">
            <a class="navbar-brand" href="/">My Page</a>
    
            <div class="collapse navbar-collapse" id="navbarColor01">
                <ul class="navbar-nav me-auto">
                    {% if current_user.is_authenticated %}
                        {% for app in current_user.app_permissions %}
                            {% if app == 'settings' %} {% continue %} {% endif %}
                            <li class="nav-item">
                                <a class="nav-link active" href="{{ url_for(get_app_url(app)) }}">{{ app.capitalize() }}</a>
                            </li>
                        {% endfor %}
                    {% endif %}
                </ul>
                <ul class="navbar-nav me-right">
                    {% if current_user.is_authenticated %}
                        <div>
                            {# 补充tabindex属性,移除错误的data-bs-content配置 #}
                            <img id="menu" src="/assets/user_icon.png" 
                                 data-bs-toggle="popover" 
                                 data-bs-trigger="focus" 
                                 tabindex="0"
                                 style="width: 32px; height: 32px; cursor: pointer;">
                        </div>
                    {% else %}
                        <form class="d-flex" method="POST" action="/login">
                            <input class="form-control me-sm-2" type="email" name="email" placeholder="email">
                            <input class="form-control me-sm-2" type="password" name="password" placeholder="password">
                            <button class="btn btn-secondary my-2 my-sm-0" type="submit">Login</button>
                        </form>
                    {% endif %}
                </ul>
            </div>
        </div>
    </nav>
    

    {# 自定义弹出内容放到template标签内,默认不显示 #}
    <template id="nav_dropdown_content">
        <ul class="list-group" style="min-width: 120px;">
            <a href="/settings" class="list-group-item list-group-item-action">Settings</a>
            <a href="/logout" class="list-group-item list-group-item-action">Logout</a>
        </ul>
    </template>
{% endblock %}

{% block scripts %}
<script type="text/javascript">
    var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
    var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
        return new bootstrap.Popover(popoverTriggerEl, {
            html: true, // 允许渲染HTML内容
            content: document.getElementById('nav_dropdown_content').innerHTML, // 加载自定义内容
            placement: 'bottom' // 固定在触发元素下方弹出
        })
    })
</script>
{% endblock %}
效果说明

修复后页面加载时不会再弹出JS报错,下拉菜单默认隐藏,点击用户头像会正常弹出Popover菜单,点击页面其他区域时菜单自动收起,全程无需引入jQuery,不会和现有React代码产生冲突。

内容的提问来源于stack exchange,提问作者user1772250

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:27:07