Jekyll中Shopify Liquid循环替换链接仅渲染最后一项问题
问题根因
- 你在Liquid的
for循环里反复声明同名的createElement函数,JavaScript中后声明的同名函数会直接覆盖之前的版本,循环结束后全局只保留最后一次(也就是pid=8那条谷歌链接)生成的函数,之前pid=6的函数完全被覆盖,这是所有位置都被替换成最后一个链接的核心原因。 - 替换逻辑没有做绑定:你的
replaceLink函数会全局遍历所有.answerspan元素做替换,不管当前链接属于哪个FAQ条目,哪怕函数不被覆盖,执行时也会把当前链接替换到所有匹配占位符的位置,不会对应到所属条目。 - 你之前观察到
console.log能按顺序打印正确链接,是因为Liquid渲染时会把每个循环里的console.log语句都保留下来按顺序执行,但同名函数只会留最后一个,所以才会出现日志看着正常、实际替换结果错误的反常情况。 - 额外冗余问题:循环里多次给
window.load绑定事件,属于不必要的重复操作。
修复方案
直接把逻辑改成:渲染阶段给每个答案块标记对应的pid,JS启动时先把所有有效链接存成键值对,页面加载完成后逐个遍历答案块,只替换当前块内的占位符为对应链接即可,不需要动态生成一堆带pid后缀的函数和变量,从根源上避免函数覆盖问题。
修改后的模板代码
首先调整FAQ渲染部分,给每个答案span加上pid标记:
<h1 class="fs-6 fw-500" align="center">Frequently Asked Questions <br> Welcome to our FAQ!</h1> <div class="accordiobody"> {% for faq in site.data.faq_yaml.frequently_asked_questions %} <div class="accordion"> <hr> <div class="container"> <div class="question fw-400"> <h1 class="fs-5 fw-500"> {{ faq.question }} </h1> </div> <div class="answer"> <blockquote> <!-- 新增data-faq-pid属性标记当前条目的pid --> <span class="answerspan" data-faq-pid="{{ faq.faq_link_pid }}"> {{ faq.answer }} </span> </blockquote> </div> </div> </div> {% endfor %} </div>
然后替换掉原来的JS逻辑,删掉循环里动态生成函数、重复绑定事件的部分:
<script type="text/javascript"> // 初始化链接映射表,key为faq pid,value为链接信息 const faqLinkMap = {}; {% for faq in site.data.faq_yaml.frequently_asked_questions %} {% if faq.hyper_link != null and faq.hyper_link != "" and faq.link_description != null and faq.link_description != "" %} faqLinkMap[{{ faq.faq_link_pid }}] = { url: "{{ faq.hyper_link }}", desc: "{{ faq.link_description }}" }; {% endif %} {% endfor %} // 页面加载完成后统一执行替换 window.addEventListener('load', function () { const allAnswerSpans = document.querySelectorAll('.answerspan'); allAnswerSpans.forEach(span => { const currentPid = span.dataset.faqPid; // 当前条目没配置链接直接跳过 if (!faqLinkMap[currentPid]) return; const {url, desc} = faqLinkMap[currentPid]; const linkTemplate = `<a href="${url}" target="_blank">${desc}</a>`; // 只替换当前答案块内的占位符,正则匹配aaaa/aaaaa及后面多余的空格 span.innerHTML = span.innerHTML.replace(/aaaa+\s*/g, linkTemplate); }); }); // 原有手风琴折叠逻辑保持不变 const accordion = document.getElementsByClassName('container'); for (i = 0; i < accordion.length; i++) { accordion[i].addEventListener('click', function () { this.classList.toggle('active'); }) } </script>
补充说明
替换用的正则调整为/aaaa+\s*/g,可以兼容你YAML里写的aaaa、aaaaa两种长度的占位符,同时会吃掉占位符后面多余的空格,替换后不会留多余空白。
内容的提问来源于stack exchange,提问作者DaOfficialWizard
相关产品推荐
相关产品推荐

