【发布时间】:2018-06-15 15:28:16
【问题描述】:
const N_COLS = 20; // use it to modify the number of columns
const N_ROWS = 20; // use it to modify the number of rows
const data = {
name: "Sample",
columns: generateColumns(N_COLS),
rows: generateRows(N_ROWS),
}
function generateColumns(n){
let columns = [];
for(let i = 0; i < n; i ++){
columns.push({ index: i, name : "Column " + i})
}
return columns;
}
function generateRows(n){
let rows = [];
for(let i = 0; i < n; i ++){
rows.push({ index: i, fields: generateFields(N_COLS)});
}
return rows;
}
function generateFields(n){
let fields = [];
for(let i = 0; i < n; i ++){
fields.push({index: i, text: "Field " + i});
}
return fields;
}
$(document).ready(function(){
console.time('Compile');
var tmpl = $.templates("#mainTemplate");
console.timeEnd('Compile');
console.time('Render');
tmpl.link("#container", data);
console.timeEnd('Render');
});
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsviews/0.9.90/jsviews.min.js"></script>
</head>
<body>
<script id="mainTemplate" type="text/x-jsrender">
<h1>{{:name}}</h1>
{{include tmpl="#contentTemplate"/}}
</script>
<script id="contentTemplate" type="text/x-jsrender">
<table>
<thead>
{{for columns}}
{{include tmpl="#columnTemplate"/}}
{{/for}}
</thead>
<tbody>
{{for rows}}
{{include tmpl="#rowTemplate"/}}
{{/for}}
</tbody>
</table>
</script>
<!-- In this example, using those templates with an include tag doesn't make sense, but that's because it's a simplified version of what I'm working with -->
<!-- In my scenario having those templates separated is a must have :( -->
<script id="columnTemplate" type="text/x-jsrender">
<th>{{:name}}</th>
</script>
<script id="rowTemplate" type="text/x-jsrender">
<tr>
{{for fields}}
{{include tmpl="#fieldTemplate"/}}
{{/for}}
</tr>
</script>
<script id="fieldTemplate" type="text/x-jsrender">
<td>
{{:text}}
</td>
</script>
<div id="container"></div>
</body>
</html>
我在 Edge 和 IE 中遇到了 JsViews 的性能问题。我有一个非常大的模板,里面有很多包含标签和很多数据链接。在 Chrome 和 Firefox 中,性能还可以,渲染时间不到 1 秒,这对我的需求很有帮助,但在 Edge 和 IE 中,几乎需要 5 秒:(
此模板可以在给定页面中使用任意多次,因此性能问题在此处逐渐增加。
我尝试使用 JsRender 而不是 JsViews,调整我的模板和对象而不使用数据链接,因为我注意到,在我的场景中,使用它们会极大地影响性能,在 Chrome 和 Firefox 中,我实现了 500 毫秒的渲染和在 IE 和 Edge 中.. 2 秒,这仍然满足我的需求。
我已经尝试简化我正在使用的模板,但我已经达到了底线..
我有很多想法可以尝试解决这个问题,这就是我的问题的来源:
是否有(或者会在新的 JsViews/JsRender 版本中)在 Web Worker 中编译模板的方法?我知道在网络工作者中我们不能使用 JQuery、访问 DOM 也不能使用具有自定义原型的对象,但谁知道.. 即使编译时间相同,至少我可以编译 并行模板。
有没有一些神奇的技巧可以提高 IE 和 Edge 中的 JsViews/JsRender 性能? (扔掉 IE 和 Edge 会很好,但不幸的是这不是一个选择:(xD)
PS:恐怕我不能发布任何类型的代码,因为我正在谈论我正在工作的企业的项目。
【问题讨论】:
-
您是否对缓慢发生的位置进行了分析?模板编译应该只发生在初始页面加载时,所以如果你在每次调用时触发模板或子模板的新编译,那是一个错误。任何模板都应该只编译一次。分析是否表明问题包括重新编译?如果没有,预编译将无济于事....
-
@BorisMoore 模板肯定会编译一次。我注意到我在网络工作者的问题中犯了一个错误,我想说“在网络工作者上渲染”而不是编译^^'
-
JsRender 不需要 jQuery(参见 jsviews.com/#jsr-quickstart)。它也不需要 DOM 来呈现。 (它呈现为 HTML 标记字符串)。但是 JsViews(和数据链接)确实需要 jQuery 和 DOM。要了解您的性能问题,您可能需要展示编码风格的示例,或者创建一个示例/jsfiddle 来说明性能问题,即使您没有显示项目中的特定代码。
-
@BorisMoore 我在 Web Worker 中使用 JsRender 时遇到了一个额外的问题,我使用自定义原型,但我想不出办法将我的对象发送给它。我知道这不是 JsRender 问题,所以顺其自然吧,我会找到解决该问题的方法:p。但是,我会尽快用 jsfiddle 更新我的问题,为您提供我的方案的方法,可能是我的模板或对象可以重新定义以提高性能,感谢您的时间:)
-
@BorisMoore 我用一个简单的 jsfiddle 更新了我的问题,试图展示我正在使用的内容。如果你在 chrome 上运行它,你会注意到编译和渲染平均需要 50 毫秒,但在 edge 中几乎需要 200 毫秒(至少在我的计算机中)。在我的真实场景中,这种差异更大,因为模板和对象更复杂。
标签: javascript web-worker jsrender jsviews