如何实现Bootstrap Popover内容动态更新?附代码求助
Hey there, let's dig into your code and fix those issues with the popover not updating correctly after clicking the purchase button! I spotted a few key problems that are causing the unexpected behavior:
1. 数组被错误覆盖,导致历史数据丢失
In the else branch of your product_buy_now function, you're using news_price_data = [20]; which completely replaces the entire array instead of adding a new element. This wipes out all previous price data, making your total price calculations wrong. Switch it to news_price_data.push(20); to preserve existing data.
2. Bootstrap Popover 未刷新更新后的内容
Once you initialize a Bootstrap popover, just updating the title and data-content attributes won't refresh the popover. You need to destroy the old instance and re-initialize it to pick up the new content.
3. 全局元素重复追加内容,导致叠加混乱
Your poH and poC elements are defined in the global scope, so every time inbox_open runs, new content gets appended to the same elements. This causes duplicate headers and content after multiple purchases. Move these element creations inside the inbox_open function to start fresh each time.
4. 重复绑定事件,导致点击多次触发
You're binding click events to the popover header buttons every time the popover shows up. This means after multiple opens, each button has multiple click handlers attached, leading to unexpected behavior. We'll fix this by binding events only once and using proper event cleanup.
修复后的完整代码
<!-- HTML --> <button class="btn btn-sm btn-danger" style="margin: 40px 0 0 0;" onclick="product_buy_now()">Click Me First</button> <button id="inbox" class="btn btn-primary btn-sm" style="margin: 40px 0 0 400px;" data-toggle="popover" data-placement="left" data-html="true" title="" data-content="">inbox</button> <!-- Script --> <script> // inbox core references var inbox = document.getElementById("inbox"); var news_from_to = []; var number_of_news = []; var news_price_data = []; // inbox.open function - now creates fresh containers each call function inbox_open(news_from_to, number_of_news, news_price_data) { console.log("Opening Executed!"); console.log("\nCraft Data:"); console.log(news_from_to); console.log(number_of_news); console.log(news_price_data); console.log(""); // Create NEW header/content containers every time to avoid duplication var poH = document.createElement("span"); var poC = document.createElement("span"); for(var i = 0; i < news_from_to.length; i++) { // Create individual header/content components var b = document.createElement("button"); var c = document.createElement("span"); b.innerHTML = (i + 1); b.className = "poH"; c.className = "poC"; c.style = "display: none;"; // Calculate total price for the current purchase batch var news_price_of_items = 0; for(var j = news_from_to[i]; j < (news_from_to[i] + number_of_news[i]); j++) { news_price_of_items += news_price_data[j]; } // Populate content with purchase details c.innerHTML = "You Bought: <br />"+ number_of_news[i]+ " items <br />"+ "for $"+ news_price_of_items; // Add to popover containers poH.appendChild(b); poC.appendChild(c); } // Update popover attributes inbox.setAttribute("title", poH.innerHTML); inbox.setAttribute("data-content", poC.innerHTML); // Refresh Bootstrap popover: destroy old instance, re-initialize $('[data-toggle="popover"]').popover('dispose'); $('[data-toggle="popover"]').popover(); console.log("Craft as Crafted:") console.log(poH.innerHTML); console.log(poC.innerHTML); } // Initialize Bootstrap popover on page load $(document).ready(function() { $('[data-toggle="popover"]').popover(); // Handle popover shown event - bind events only once with cleanup $('#inbox').on('shown.bs.popover', function () { var poHs = document.getElementsByClassName("poH"); var poCs = document.getElementsByClassName("poC"); // Unbind existing click handlers before adding new ones for(var i = 0; i < poHs.length; i++) { poHs[i].removeEventListener('click', window['popoverHandler_' + i]); window['popoverHandler_' + i] = popoverClickHandler(i, poHs, poCs); } // Set initial active state for first item poHs[0].className += " seen active"; poCs[0].style = "display: block;"; }); }); // Reusable popover click handler - stored globally for easy unbinding function popoverClickHandler(index, poHs, poCs) { var handler = function() { // Reset all items to inactive/hidden for(var j = 0; j < poHs.length; j++) { poHs[j].className = poHs[j].className.replace(" active", ""); } for(var j = 0; j < poCs.length; j++) { poCs[j].style = "display: none;"; } // Activate current item this.className += " seen active"; poCs[index].style = "display: block;"; }; poHs[index].addEventListener('click', handler); return handler; } /* PRODUCT BUY NOW FUNCTIONALITY */ var now_cart_item = []; var now_cart_in_item = []; function product_buy_now() { // Update inbox data based on existing purchases if(news_from_to.length == 0) { console.log("if branch:\n"); news_from_to = [0]; number_of_news = [1]; news_price_data = [10]; // Replace with your actual product price logic inbox_open(news_from_to, number_of_news, news_price_data); } else { console.log("else branch:\n"); news_from_to.push(news_price_data.length); number_of_news.push(1); news_price_data.push(20); // Fixed: push instead of overwrite array inbox_open(news_from_to, number_of_news, news_price_data); } // Clear cart for next purchase now_cart_item = []; now_cart_in_item = []; } </script>
关键修复点说明
- Preserve Purchase Data: Using
push()instead of overwriting the price array keeps all historical purchase records intact. - Fresh Popover Containers: Creating new
poHandpoCelements each timeinbox_openruns prevents content duplication. - Popover Refresh: Destroying and re-initializing the popover ensures the updated title/content is displayed.
- Clean Event Binding: Storing handlers globally and unbinding before re-binding avoids multiple click triggers.
内容的提问来源于stack exchange,提问作者S4UR000N

