从这个测试结果中可以看到,{{#prop}}{{/prop}}之间的模板内容根据prop所引用的数组迭代了两次,并且在这对标签内部直接通过{{name}}标签,输出了数组元素对象上的name属性对应的值。
如果prop属性所引用的是一个函数,但是这个函数返回值是一个数组类型,那么仍然会进行for-each渲染:
<script type="text/html"> -{{#prop}}{{name}},{{/prop}}- </script> <script> var tpl2 = document.getElementById('tpl2').innerHTML.trim(); Mustache.parse(tpl2); console.log(Mustache.render(tpl2, { prop: function(){ return [{name: 'jason'}, {name: 'frank'}]; } }));//-jason,frank,- </script>
3) 动态渲染
当prop属性所引用的是一个函数,并且这个函数的返回值还是一个函数的话,mustache会再次调用这个返回的函数,并给它传递2个参数:text表示原来的模板内容,render表示mustache内部的执行渲染的对象,以便在这个函数内部可以通过这render对象,结合原来的模板内容,自定义渲染的逻辑,并把函数的返回值作为渲染结果(这个返回值渲染的逻辑跟{{prop}}标签完全一样):
<script type="text/html"> -{{#prop}}content{{/prop}}- </script> <script> var tpl2 = document.getElementById('tpl2').innerHTML.trim(); Mustache.parse(tpl2); console.log(Mustache.render(tpl2, { prop: function(){ return function (text, render) { return "<b>" + render(text) + "</b>" }; } }));//-<b>content</b>- </script>
6. {{^prop}}{{/prop}}标签
这对标签,与{{#prop}}{{/prop}}的if-else渲染执行相反逻辑,即只有在prop属性不存在,或者引用的是一个falsy值,或者是一个空数组的时候才会显示标签之间的内容,否则不会显示:
<script type="text/html"> -{{^prop}}content{{/prop}}- </script> <script> var tpl2 = document.getElementById('tpl2').innerHTML.trim(); Mustache.parse(tpl2); //测试falsy值 console.log(Mustache.render(tpl2, {prop: ''}));//-content- console.log(Mustache.render(tpl2, {prop: 0}));//-content- console.log(Mustache.render(tpl2, {prop: null}));//-content- console.log(Mustache.render(tpl2, {prop: undefined}));//-content- console.log(Mustache.render(tpl2, {prop: false}));//-content- console.log(Mustache.render(tpl2, {prop: NaN}));//-content- // 测试空数组 console.log(Mustache.render(tpl2, {prop: []}));//-content- // 测试不存在的属性 console.log(Mustache.render(tpl2, {prop2: true}));//-content- //测试function console.log(Mustache.render(tpl2, { prop: function () { } }));//-content- console.log(Mustache.render(tpl2, { prop: function () { return false; } }));//-content- console.log(Mustache.render(tpl2, { prop: function () { return []; } }));//-content- //测试简单对象 console.log(Mustache.render(tpl2, {prop: {name: 'jason'}}));//-- //测试日期对象 console.log(Mustache.render(tpl2, {prop: new Date()}));//-- // 测试非空数组 console.log(Mustache.render(tpl2, {prop: [{name: 'jason'},{name: 'tom'}]}));//-- //测试boolean number string console.log(Mustache.render(tpl2, {prop: true}));//-- console.log(Mustache.render(tpl2, {prop: 1.2}));//-- console.log(Mustache.render(tpl2, {prop: 'yes'}));//-- //测试返回非falsy,非空数组的function console.log(Mustache.render(tpl2, { prop: function () { return 'it\'s a fun' } }));//-- //测试返回function的function console.log(Mustache.render(tpl2, { prop: function () { return function(text,render){ return '<b>' + render(text) +'</b>' } } }));//-- </script>
7. 渲染上下文
mustache有一个渲染上下文栈的概念,在模板渲染的开始的时候,把数据源对象作为当前的渲染上下文 ,并压入上下文栈。在遇到{{#prop}}标签的时候,如果prop引用的是一个对象或者是一个非空的对象数组,或者prop引用的是一个函数,并且这个函数返回的是一个对象或者是一个非空的对象数组,就会把这个对象或者数组的元素作为当前渲染上下文,并压入上下文栈,当这个标签渲染完毕的时候,才会把该上下文弹出,恢复上一层标签所使用的上下文。由于{{#prop}}标签可以多层嵌套,所以在有的模板渲染的时候,会有多层上下文存在。mustache在解析标签时,根据标签名称查找当前上下文对象是否存在该属性,如果不存在就会到上层上下文对象中查找,只要在某一层找到,就会用该层上下文对象的值来渲染。
<script type="text/html"> -{{#person}}{{#student}}{{#address}}address: {{home}},age: {{age}}{{/address}}{{/student}}{{/person}}- </script> <script> var tpl2 = document.getElementById('tpl2').innerHTML.trim(); var obj2 = { age: 20, person: { student: { address: { home: 'xxxxx' } } } }; console.log(Mustache.render(tpl2, obj2));//-address: xxxxx,age: 20- </script>