我有一个页面,在网格中按字母组合联系人。对于我更大的联系人(1000-1500),网格负载非常慢(分钟)。但是,浏览器几乎锁定,所以人们认为它崩溃了。嵌套模板foreach性能
根据铬探查器,我花了91%的时间在我最近的最大敌人.InnerHTML()。
从我可以告诉我,当填写联系人observables时,我不发出不必要的通知。
我试图提炼出页面到这个jsFiddle中的一个简单的窗体。
http://jsfiddle.net/DCLaR/105/(感谢瑞安Rahlf固定这)
它看起来像简单的版本罢了好了,所以必须有其他人在混合什么。
我打算继续并发布我的整页html,尽管它有点乱。
开始于实际网页代码中的小提琴,不退出运行,也许是太复杂,在那里馅:http://jsfiddle.net/DCLaR/108/
也许有人可以发现一些关闭或已知能够导致性能问题。
我看到了This这个问题是相似的,但没有得到它的解决方案。
的HTML
<button id="btnSaveOrg" data-bind="click: $root.SaveAll">Save All</button><span data-bind="html: SaveStatus"></span>
<table class="orgTable">
<tr>
<td>
<ul id="orgList" data-bind="template: { name: 'orgChartTemplate', foreach: DepartmentHierarchy }" style="display:none"></ul>
<div id="orgChart2" class="orgChart"></div>
</td>
<td data-bind="with: SelectedDepartment">
<div class="departmentContainer">
<span class="departmentTitle" data-bind="text: DepartmentName" ></span>
<div class="buttonBar">
<a title="Edit Department" data-bind="click: $root.BeginEdit, visible: $root.InDisplayMode">
<img src="/Images/iconEdit.png" alt="Edit" />
</a>
<a title="Add Department" data-bind="click: $root.BeginAdd, visible: $root.InDisplayMode">
<img src="/Images/iconAdd.png" alt="Add" />
</a>
</div>
<div class="departmentInnerContainer">
<div id="departmentTabs" data-bind="kendoTabStrip: {}">
<ul>
<li class="k-state-active" data-bind="visible: IsRoot">All Company Contacts</li>
<li class="k-state-active" data-bind="visible: IsNotRoot">Department Contacts</li>
<li data-bind="visible: IsNotRoot">Associate Contacts</li>
</ul>
<div id="allContacts">
<div class="buttonBar">
Find: <input type="text" data-bind="value: $root.CurrentDepartmentContacts.SearchStringText" /><a data-bind=" click: $root.CurrentDepartmentContacts.Search"><img src="/Images/iconSearch.png" /></a>
</div>
<div data-bind="template: { name: 'ContactListTemplate', foreach: $root.CurrentDepartmentContacts }"></div>
</div>
<div id="currentContacts">
<div class="buttonBar">
Find: <input type="text" data-bind="value: $root.CurrentDepartmentContacts.SearchStringText" /><a data-bind=" click: $root.CurrentDepartmentContacts.Search"><img src="/Images/iconSearch.png" /></a>
</div>
<div data-bind="template: { name: 'ContactListTemplate', foreach: $root.CurrentDepartmentContacts }"></div>
</div>
<div id="assocContacts">
<div>
<input type="checkbox" data-bind="checked: $root.ShowAssociatedContacts" /> Show Contacts tied to departments<br />
<input data-bind="value: $root.ContactSearchText" /><a data-bind="click: $root.SearchAllContacts "><img src="/Images/iconSearch.png" /></a>
<br />
<button data-bind="click: $root.CheckAllContacts">Check All</button> <button data-bind="click: $root.UncheckAllContacts">Uncheck All</button>
</div>
<!-- ko if: $root.AllContactsSearchResult().length>0 -->
<div class="contactsContainerOrg" data-bind="foreach: $root.AllContactsSearchResult">
<div>
<input type="checkbox" data-bind="checked: IsChecked" /><span data-bind="html: ContactName"></span>
</div>
</div>
<!-- /ko -->
<!-- ko if: $root.AllContactsSearchResult().length==0 -->
<div class="contactsContainerOrg">
<div>
No Contacts Found
</div>
</div>
<!-- /ko -->
<button data-bind="click: $root.AssociateSelectedContacts, enable: $root.AssociatedContactsChecked">Associate Contacts</button>
</div>
</div>
</div>
</div>
</td>
</tr>
</table>
<div id="divAddEditDepartment" style="display:none">
<span data-bind="template: { name: 'editDeptTemplate', foreach: EditingDepartment }"></span>
</div>
<script type="text/html" id="OldDept">
<div class="departmentContainer">
<button id="Button1" data-bind="click: $root.AddDepartment, visible: $root.InDisplayMode">Add Department</button>
<fieldset class="departmentFieldSet">
<legend>Selcted Department</legend>
<span data-bind="template: { name: 'viewDeptTemplate', foreach: SelectedDepartment }, visible: InDisplayMode"></span>
<span data-bind="template: { name: 'editDeptTemplate', foreach: SelectedDepartment }, visible: InEditMode"></span><br /><br />
<b>Contacts</b><br />
Search: <input type="text" data-bind="value: $root.ContactsVM.SearchString" /><br />
<div data-bind="template: { name: 'ContactListTemplate', foreach: $root.ContactsVM }"></div>
</fieldset>
</div>
</script>
<asp:HiddenField ID="hdnCustomerId" Value="7" runat="server"/>
<!-- Tempaltes -->
<script type="text/html" id="orgChartTemplate">
<li data-bind="attr: { DeptId: CustomerDepartmentId }">
<div class="innerNode" data-bind="css: { selectedNode: IsSelected }">
<img src="/Images/Contacts/CompanyOrg.png" /><span style="font-weight:bold;display:block" data-bind="html: DepartmentName"></span> <br /><br />
</div>
<ul data-bind="template: { name: 'orgChartTemplateChild', foreach: Children }"></ul>
</li>
</script>
<script type="text/html" id="orgChartTemplateChild">
<li data-bind="attr: { DeptId: CustomerDepartmentId }">
<div class="innerNode" data-bind="css: { selectedNode: IsSelected }">
<span style="font-weight:bold" data-bind="html: DepartmentName"></span> <br /><br />
<span data-bind="html: ContactCountDisplay"></span>
</div>
<ul data-bind="template: { name: 'orgChartTemplateChild', foreach: Children }"></ul>
</li>
</script>
<script type="text/html" id="viewDeptTemplate">
<div class="noWrap"> <label>Department Name:</label><div style="width: 12px; display: inline-block;" /><span data-bind="text: DepartmentName"></span></div> <br />
<span data-bind="visible: $root.IsNew">
<span class="noWrap"> <label>Parent Department:</label><span style="width: 5px; display: inline-block;"/><span data-bind="text: ParentDepartmentName"> </span></span>
</span>
<br /><br />
<button data-bind="click: $root.BeginEdit">Edit</button>
</script>
<%--Edit template markup--%>
<script type="text/html" id="editDeptTemplate" >
<div class="noWrap"> <label>Department Name:</label><div style="width: 12px; display: inline-block;" /><input type="text" data-bind="value: DepartmentName" required="required"> <span id="reqDepartmentError" style="color: red; display: none;">*</span></div><br />
<div class="noWrap"><label>Parent Department:</label><div style="width: 5px; display: inline-block;"/><select data-bind="options: $root.GetParentCustomerDepartmentOptions(), optionsText: 'DepartmentName', optionsValue: 'CustomerDepartmentId', value: ParentCustomerDepartmentId" ></select></div><br />
</script>
<script type="text/html" id="ContactListTemplate">
<div id="Div1" class="contactsContainerOrg" data-bind="foreach: ContactGroups">
<div class="contactGroupHeader" data-bind="text: GroupName, attr: { groupName: GroupName }"></div>
<div class="contactGroupContainer">
<div data-bind="template: { name: $root.GetContactTemplate, foreach: Contacts }">
</div>
</div>
</div>
<div data-bind="if: ShowGroupBy">
<span data-bind="foreach: AllLetterContactGroups">
<span class="groupList" data-bind="text: GroupName, click: $root.ScrollToGroup, style: { fontWeight: HasContacts() ? '900' : '300', fontSize: HasContacts() ? '12px' : '10px' }"></span>
</span>
</div>
</script>
<script type="text/html" id="ContactLine">
<div class="contactListItem" data-bind="text: ContactName, click: $root.CurrentDepartmentContacts.SelectContact, css: { contactListItemSelected: IsSelected() == true }"></div>
</script>
<script type="text/html" id="ContactDetails">
<div class="contactDetails">
<div>
<h2>
<span data-bind="text: ContactName" style="color: #054b73"></span>
</h2>
<label>Office Phone: </label>
<span data-bind="text: OfficePhone"></span>
<label>ext:</label>
<span data-bind="text: OfficePhoneExt"></span>
<br />
<label>Fax: </label>
<span data-bind="text: Fax"></span>
<br />
<label>Email: </label>
<span data-bind="text: Email"></span>
</div>
</div>
</script>
<script type="text/javascript">
var customerId = $("[id$=hdnCustomerId]").val();
var orgModel = new CustomerOrgVM(customerId, "orgList", "orgChart2", 'divAddEditDepartment');
function LoadCustomerOrgChart() {
orgModel.LoadDepartments();
ko.bindingHandlers.kendoTabStrip.animation = false;
ko.applyBindings(orgModel);
$w.Util.WaitAll(function() {
// Build the Hierarchy after all departments and contacts have been loaded
orgModel.BuildHierarchy();
orgModel.IsLoaded(true);
// Load Contacts Async after hierarchy is displayed
orgModel.LoadContacts();
});
}
</script>
JavaScript的
好的眼光在报价,我要更新问题中的小提琴。我喜欢自定义绑定的想法,但会留下一个问题,看看其他人是否有其他优点 –
嗯,在玩这个例子中的数字后,看起来我有另一个隐藏在某个地方的问题。我可以在每封信中做100个项目,并且仍然可以像第二个一样加载。 –
其中一些将取决于您的内部绑定对于每个元素模板的复杂程度。例如,如果您在1500个元素上执行大型ko.com或15个元素,则会降低您的速度。而且,正如我所提到的,长时间延迟可能不仅仅是渲染,它可能包括检索数据并解析或映射它。 –