Bootstrap Vue b-tabs内无法渲染Axios请求返回HTML怎么办
核心故障原因
- Bootstrap Vue 的
b-tab默认不会把非激活标签页的内容渲染到真实 DOM 中,你的第二个标签页对应的#app2节点在页面刚加载时根本不存在,vm2挂载时找不到目标节点,直接失效,自然不会执行里面的 Axios 请求逻辑。 - 拆分多个独立 Vue 实例的写法,在
b-tabs这种会动态操作 DOM 的组件里非常容易出现节点找不到、作用域混乱的问题,完全没必要。 - 你猜测的
compile相关能力完全用不上,属于过度设计,问题根源和 HTML 编译没有关系。
注意:Bootstrap Vue 的
b-tabs内部DOM是动态生成的,只要标签页没被激活过,对应内容节点就不会出现在DOM树里,提前挂载的Vue实例自然找不到目标。
修复方案
把所有逻辑合并到同一个挂载在 #tabby 的 Vue 实例中,配合 b-tabs 的切换事件动态加载对应标签页的数据,全程用 Vue 响应式数据控制渲染,不需要额外的独立实例和 jQuery 操作。
修改后的页面代码
不需要保留原来的 #app、#app2 独立节点标识,直接调整结构即可:
<div id="tabby"> <b-tabs v-model="activeTab"> <b-tab title="Atari 2600" name="atari2600"> <b-spinner v-if="loading.atari2600" style="display: block; margin-left:auto; margin-right:auto; margin-top:200px;" ></b-spinner> <div v-else v-html="results.atari2600"></div> </b-tab> <b-tab title="3DS" name="3ds"> <b-spinner v-if="loading['3ds']" style="display: block; margin-left:auto; margin-right:auto; margin-top:200px;" ></b-spinner> <div v-else v-html="results['3ds']"></div> </b-tab> </b-tabs> </div>
对应的 Vue 逻辑代码
const apiBase = "someurl"; new Vue({ el: '#tabby', data: { activeTab: 'atari2600', // 按标签页key存储对应渲染的HTML内容 results: { atari2600: '', '3ds': '' }, // 按标签页key存储加载状态 loading: { atari2600: false, '3ds': false }, // 已加载过的标签页,避免重复请求 loadedTabs: [] }, mounted() { // 初始化加载默认激活的标签页内容 this.loadTabContent(this.activeTab); }, watch: { // 监听标签页切换,激活时自动加载对应内容 activeTab(newTab) { this.loadTabContent(newTab); } }, methods: { loadTabContent(tabName) { // 已加载过的内容不重复请求 if (this.loadedTabs.includes(tabName)) return; this.loading[tabName] = true; axios.get(apiBase, {params: { section: tabName }}) .then(response => { this.results[tabName] = response.data; this.loadedTabs.push(tabName); }) .finally(() => { this.loading[tabName] = false; }); } } });
额外说明
- 所有标签页的激活状态、内容、加载状态都由同一个实例的响应式数据管理,不会再出现DOM节点找不到的问题。
- 不需要手动操作隐藏加载组件,用
v-if绑定加载状态自动控制显隐即可,完全去掉了jQuery依赖。 - 只在标签页首次激活时请求对应数据,已经加载过的内容会直接保留,不会重复发起请求。
v-html可以正常渲染Axios返回的HTML内容,不需要额外的编译操作。
内容的提问来源于stack exchange,提问作者argossol
相关产品推荐
相关产品推荐

