如何将JS变量传递给Pug并修改Pug循环所使用的变量
问题根因
- Pug的
each循环是服务端渲染阶段执行的,早于浏览器解析运行客户端JS的阶段,你在script标签中定义的users2属于客户端运行时变量,不可能反向传递给服务端的Pug模板逻辑。报错Cannot read property 'length' of undefined就是因为服务端渲染时users2变量不存在,你能直接在Pug模板语法中使用的只有后端传入的原始users变量。 - 你现有的
var users2 = '#{users}';写法也有问题,插值出来的是数组转义后的字符串,不是可操作的对象数组,正确的序列化写法是var users2 = !{JSON.stringify(users)};。
修复方案
方案1:纯客户端渲染(适配实时搜索过滤场景)
完全弃用Pug的each循环渲染列表,把数据序列化到客户端后用JS统一控制渲染和更新:
section.p-0.md-p-5.muli // 给列表容器加ID方便操作 .flex.flex-wrap#userList script. // 正确序列化服务端传入的用户数组 const allUsers = !{JSON.stringify(users)}; const userListEl = document.getElementById('userList'); const searchBar = document.getElementById('searchBar'); // 封装列表渲染函数 function renderUserList(users) { userListEl.innerHTML = users.map(user => ` <div class="w-100pc md-w-33pc p-10"> <a class="block no-underline p-5 br-8 hover-bg-indigo-lightest-10 hover-scale-up-1 ease-300 filePage" href="/${user.slug}"> <img class="w-100pc" src="${user.photoUrl[0]}" alt=""> <p class="fw-600 white fs-m3 mt-3"> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed… </p> <div class="indigo fs-s3 italic after-arrow-right my-4">3 days ago by Jeff</div> </a> </div> `).join(''); } // 初始渲染全量用户列表 renderUserList(allUsers); // 搜索触发过滤重渲染 searchBar.addEventListener('keyup', (e) => { const searchVal = e.target.value.toLowerCase(); const filteredUsers = allUsers.filter(user => { // 此处替换为你实际需要匹配的用户字段,比如用户名、slug等 return user.slug.toLowerCase().includes(searchVal); }) renderUserList(filteredUsers); });
方案2:DOM显示/隐藏过滤(保留Pug渲染初始列表的逻辑)
如果不需要重渲染内容,只是做搜索筛选,可以给Pug渲染的每个项加匹配属性,搜索时直接控制DOM的显示隐藏:
section.p-0.md-p-5.muli .flex.flex-wrap each user in users // 给每个项加自定义属性存匹配字段 .w-100pc.md-w-33pc.p-10.user-item(data-search-key=user.slug) a.block.no-underline.p-5.br-8.hover-bg-indigo-lightest-10.hover-scale-up-1.ease-300.filePage(href=`/${user.slug}`) img.w-100pc(src=`${user.photoUrl[0]}` alt='') p.fw-600.white.fs-m3.mt-3 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed… .indigo.fs-s3.italic.after-arrow-right.my-4 3 days ago by Jeff script. const searchBar = document.getElementById('searchBar'); const userItems = document.querySelectorAll('.user-item'); searchBar.addEventListener('keyup', (e) => { const searchVal = e.target.value.toLowerCase(); userItems.forEach(item => { const matchKey = item.dataset.searchKey.toLowerCase(); item.style.display = matchKey.includes(searchVal) ? 'block' : 'none'; }) });
内容的提问来源于stack exchange,提问作者Stan1234
相关产品推荐
相关产品推荐

