TYPO3:在子页面插入HTML(含可切换Pills)的最优方案
嘿,我太懂复制粘贴重复HTML代码的烦恼了——不仅冗余,后期改起来要找好几个地方,简直是维护噩梦!针对你带下拉菜单导航的项目里重复使用Bootstrap Pills的需求,这里有几个更优雅的解决方案,你可以根据自己的技术栈选:
1. 原生HTML模板(纯静态页面友好)
用HTML5的<template>标签定义你的Pills模板,然后通过JavaScript动态插入到需要的页面中。这样模板只写一次,哪里需要就调用哪里。
示例代码:
<!-- 在页面头部定义模板 --> <template id="pills-template"> <ul class="nav nav-pills" id="pills-tab" role="tablist"> <li class="nav-item" role="presentation"> <button class="nav-link active" id="pills-home-tab" data-bs-toggle="pill" data-bs-target="#pills-home" type="button" role="tab" aria-controls="pills-home" aria-selected="true">Home</button> </li> <li class="nav-item" role="presentation"> <button class="nav-link" id="pills-profile-tab" data-bs-toggle="pill" data-bs-target="#pills-profile" type="button" role="tab" aria-controls="pills-profile" aria-selected="false">Profile</button> </li> </ul> <div class="tab-content" id="pills-tabContent"> <div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab">Home content...</div> <div class="tab-pane fade" id="pills-profile" role="tabpanel" aria-labelledby="pills-profile-tab">Profile content...</div> </div> </template> <!-- 在需要展示Pills的地方留个容器 --> <div id="pills-container"></div> <script> // 动态插入模板内容 const template = document.getElementById('pills-template'); const container = document.getElementById('pills-container'); const clone = document.importNode(template.content, true); container.appendChild(clone); // 别忘了初始化Bootstrap Pills(如果页面没自动初始化的话) const pills = new bootstrap.Tab(document.getElementById('pills-tab')); </script>
如果不同页面的Pills内容有差异,还可以通过JS动态修改克隆后的内容,比如替换tab标题、内容等。
2. 服务器端模板复用(有后端项目适用)
如果你的项目用了后端语言(比如PHP、Node.js、Python),可以把Pills做成一个单独的组件文件,然后在需要的页面通过模板引擎引入。
举个PHP的例子:
- 新建
components/bootstrap-pills.php,把Pills的HTML代码放进去 - 在需要的页面里引入:
<?php include 'components/bootstrap-pills.php'; ?>
Node.js的话用EJS、Handlebars这类模板引擎,语法类似<%- include('components/bootstrap-pills.ejs') %>,后端渲染时会自动把组件内容插入到页面里。
3. 前端框架组件化(SPA或现代前端项目)
如果你的项目用了Vue、React这类前端框架,直接把Bootstrap Pills封装成可复用组件是最灵活的方案。你可以通过props传递不同的tab数据,实现不同页面展示不同内容的Pills。
举个Vue组件的简单示例:
<!-- BootstrapPills.vue --> <template> <div> <ul class="nav nav-pills" role="tablist"> <li class="nav-item" role="presentation" v-for="(tab, index) in tabs" :key="index"> <button class="nav-link" :class="{ active: index === activeTab }" :id="`pills-${tab.id}-tab`" data-bs-toggle="pill" :data-bs-target="`#pills-${tab.id}`" type="button" role="tab" :aria-controls="`pills-${tab.id}`" :aria-selected="index === activeTab" @click="activeTab = index" > {{ tab.title }} </button> </li> </ul> <div class="tab-content"> <div class="tab-pane fade" :class="{ 'show active': index === activeTab }" :id="`pills-${tab.id}`" role="tabpanel" :aria-labelledby="`pills-${tab.id}-tab`" v-for="(tab, index) in tabs" :key="index" > {{ tab.content }} </div> </div> </div> </template> <script setup> import { ref } from 'vue'; const props = defineProps({ tabs: { type: Array, required: true, default: () => [] } }); const activeTab = ref(0); </script>
然后在需要的页面直接使用:
<BootstrapPills :tabs="[ { id: 'home', title: 'Home', content: 'Home page content' }, { id: 'profile', title: 'Profile', content: 'Profile page content' } ]" />
4. 纯JS动态生成(无需模板引擎/框架)
如果不想用模板或框架,也可以直接用JavaScript动态创建Pills的DOM元素,适合需要根据动态数据生成Pills的场景。
示例代码:
// 定义Pills的配置数据 const pillsConfig = { tabs: [ { id: 'home', title: 'Home', content: 'Welcome to home!' }, { id: 'settings', title: 'Settings', content: 'Manage your settings here' } ] }; // 创建Pills导航 const nav = document.createElement('ul'); nav.className = 'nav nav-pills'; nav.id = 'pills-tab'; nav.setAttribute('role', 'tablist'); pillsConfig.tabs.forEach((tab, index) => { const li = document.createElement('li'); li.className = 'nav-item'; li.setAttribute('role', 'presentation'); const button = document.createElement('button'); button.className = `nav-link ${index === 0 ? 'active' : ''}`; button.id = `pills-${tab.id}-tab`; button.setAttribute('data-bs-toggle', 'pill'); button.setAttribute('data-bs-target', `#pills-${tab.id}`); button.setAttribute('type', 'button'); button.setAttribute('role', 'tab'); button.setAttribute('aria-controls', `pills-${tab.id}`); button.setAttribute('aria-selected', index === 0); button.textContent = tab.title; li.appendChild(button); nav.appendChild(li); }); // 创建Tab内容区 const tabContent = document.createElement('div'); tabContent.className = 'tab-content'; tabContent.id = 'pills-tabContent'; pillsConfig.tabs.forEach((tab, index) => { const pane = document.createElement('div'); pane.className = `tab-pane fade ${index === 0 ? 'show active' : ''}`; pane.id = `pills-${tab.id}`; pane.setAttribute('role', 'tabpanel'); pane.setAttribute('aria-labelledby', `pills-${tab.id}-tab`); pane.textContent = tab.content; tabContent.appendChild(pane); }); // 把生成的元素插入到页面容器里 const container = document.getElementById('pills-container'); container.appendChild(nav); container.appendChild(tabContent); // 初始化Bootstrap Pills new bootstrap.Tab(document.getElementById('pills-tab'));
这样你只需要修改pillsConfig里的数据,就能生成不同的Pills,完全不用复制粘贴HTML!
内容的提问来源于stack exchange,提问作者Hans Martin

