Bootstrap 3.3.7点击按钮时API动态加载Popover内容异步问题
解决Bootstrap 3.3.7 Popover异步加载API内容的问题
这个问题我之前也碰到过,Bootstrap 3的Popover确实不支持直接在content里用异步函数返回内容——它的content函数是同步执行的,会立刻拿你的返回值去渲染弹窗,根本等不及你的API请求完成,所以你之前不管用then还是async/await,要么返回undefined要么返回Promise对象,自然显示不对。
这里给你两个可行的解决方案,核心思路都是先让Popover显示一个临时内容(比如加载提示),等API请求完成后再替换成真实内容:
方案一:在content函数内发起异步请求并更新内容
直接在content函数里先返回加载提示,然后立刻发起API请求,请求完成后找到当前Popover的内容容器更新内容:
$('a').popover({ content: function(){ // 先返回加载中的提示 const loadingText = '<span>加载中...</span>'; const $currentBtn = $(this); // 发起API请求 fetch('https://jsonplaceholder.typicode.com/todos/1') .then(response => response.json()) .then(json => { // 拿到API返回的内容后,更新Popover的内容 $currentBtn.data('bs.popover').tip().find('.popover-content').html(json.title); }) .catch(() => { // 处理请求失败的情况 $currentBtn.data('bs.popover').tip().find('.popover-content').html('加载失败,请重试'); }); return loadingText; } });
方案二:监听Popover的shown事件更新内容
这种方法更清晰,先给Popover设置初始的加载内容,然后监听shown.bs.popover事件(弹窗显示后触发),在事件回调里发起请求并更新内容:
// 初始化Popover,设置初始加载提示 $('a').popover({ content: '加载中...' }).on('shown.bs.popover', function(){ const $currentBtn = $(this); fetch('https://jsonplaceholder.typicode.com/todos/1') .then(response => response.json()) .then(json => { $currentBtn.data('bs.popover').tip().find('.popover-content').html(json.title); }) .catch(() => { $currentBtn.data('bs.popover').tip().find('.popover-content').html('加载失败,请重试'); }); });
优化:避免重复请求API
如果不想每次点击都请求API,可以加个缓存机制,把已经加载过的内容存起来,下次直接用:
$('a').each(function(){ const $currentBtn = $(this); let cachedContent = null; // 用来缓存已加载的内容 $currentBtn.popover({ content: function(){ // 如果有缓存内容,直接返回 if (cachedContent) { return cachedContent; } const loadingText = '<span>加载中...</span>'; fetch('https://jsonplaceholder.typicode.com/todos/1') .then(response => response.json()) .then(json => { cachedContent = json.title; $currentBtn.data('bs.popover').tip().find('.popover-content').html(cachedContent); }) .catch(() => { cachedContent = '加载失败,请重试'; $currentBtn.data('bs.popover').tip().find('.popover-content').html(cachedContent); }); return loadingText; } }); });
这样第一次点击会请求API并缓存结果,后续点击直接显示缓存的内容,不用再发起请求了。
内容的提问来源于stack exchange,提问作者gixlg
相关产品推荐
相关产品推荐

