You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动