Mustache.js报错TypeError: Invalid template!如何保留模板清空表格行?
解决mustache.js模板被意外移除导致的后续渲染错误问题
你完全猜对了问题的根源!问题就出在模板的存放位置上——你把<script type="text/template" id="studentsTemplate">放在了<tbody id="studentsList">的内部,当你调用list.empty()或者直接设置innerHTML = html时,tbody里的所有内容(包括这个模板脚本)都会被清空。等到第二次选择年份时,$('#studentsTemplate').html()就无法获取到模板内容,自然会抛出「模板是undefined」的错误。
这里给你两种简单有效的解决方案:
方案1:将模板移到tbody外部(推荐)
把模板脚本从tbody里挪出来,比如放到表格外面的容器中或者body末尾,这样不管怎么清空tbody,模板都不会被误删。修改后的DOM结构如下:
<div class="container" style="margin-top:3%"> <label>Year</label> <select id="year" onchange="refreshList(this)"> <option value=""></option> <option value="2019">2019</option> <option value="2018">2018</option> </select> <br /><br /> <table> <thead> <tr> <th>Registered Date</th> <th>Name</th> <th>Age</th> </tr> </thead> <tbody id="studentsList"></tbody> </table> <!-- 模板移到这里,脱离tbody的管辖 --> <script type="text/template" id="studentsTemplate"> {{#students}} <tr class='row_{{id}}'> <td>{{registered}}</td> <td>{{name}}</td> <td>{{age}}</td> </tr> {{/students}} </script> </div>
这个方案不仅解决了问题,还让DOM结构更符合语义——模板本来就不属于表格内容的一部分,放在tbody里其实是不规范的写法。
方案2:提前缓存模板内容
如果不想改动现有DOM结构,可以在页面加载时就把模板内容缓存到变量里,后续渲染直接使用这个变量,不用每次去DOM中查找。修改你的JS代码如下:
// 页面加载完成后立即缓存模板内容 const studentTemplate = $('#studentsTemplate').html(); var testing = { "name" : "student-collection", "students" : [ { "id" : 97, "registered" : "2018-03-01", "name" : "John", "age" : 20 }, { "id" : 118, "registered" : "2019-04-01", "name" : "Mary", "age" : 21 }, { "id" : 509, "registered" : "2018-08-01", "name" : "Dave", "age" : 19 } ] }; function inYear(registerYear){ return function(student){ var date = new Date(student.registered); return date.getFullYear() == Number(registerYear); } } function refreshList(selected){ var filters = testing.students.filter(inYear(selected.value)); // 使用缓存的模板字符串 var html = Mustache.render(studentTemplate, {students : filters}); var list = $("#studentsList"); list.empty(); list.append(html); } function refreshList2(selected){ var filters = testing.students.filter(inYear(selected.value)); var html = Mustache.render(studentTemplate, {students : filters}); document.getElementById("studentsList").innerHTML = html; }
这样即使后续模板被清空,我们已经提前保存了模板的字符串内容,依然能正常调用Mustache.render进行渲染。
内容的提问来源于stack exchange,提问作者len




