我有下面的代码。当我选中或取消选中复选框时,chrome 会停止执行 Javascript。它给出了控制台消息
[Violation] 'change' handler took 475ms
.
我尽我所能地尝试改进代码,我减少了重复的 jQuery 选择器,使用文档片段来构建 DOM 内容,但它仍然让 Chrome 放弃执行 Javascript。我已经将它从 2000+ms 减少到大约 500ms。
我还能做什么?大约有 250 个国家/地区可能存在问题。在此之后,我将不得不对更多项目做类似的事情,所以这将是一个真正的泡菜。任何建议都将非常受欢迎。谢谢
HTML/PHP/Javascript:
<script>
var countries = <?=getVar('freelancerCountries')?>;
var languages = <?=getVar('freelancerLanguages')?>;
var countryRanks = <?php $r = getVar('countryRanks'); echo ($r?$r:'{}')?>;
$(document).ready(initFreelancerSettings);
</script>
<div id="countries" class="block small-top">
<h3>Countries</h3>
<div class="top">
<label>Default rank: <input type="number" class="default-rank xxs"/></label>
<label>Filter: <input type="text" class="filter xs" /></label>
</div>
<ul class="bottom list">
</ul>
<button class="save">Save</button>
</div>
Javascript:
function updateCountryRankForElement(element)
{
var code = $(element).closest('[data-code]').data('code')
if ($(`#countries [data-code=${code}] [type=checkbox]`).prop('checked'))
countryRanks[code] = $(`#countries [data-code=${code}] [type=number]`).val();
else
delete countryRanks[code];
}
function updateCountryList() {
// Cache DOM elements
var $list = $('#countries .list');
var $filter = $('#countries .filter');
var $defaultRank = $('#countries .default-rank');
// Create document fragment
var fragment = document.createDocumentFragment();
// Get filter value
var filter = $filter.val().toLowerCase();
// Filter and sort countries
var sortedFiltered = Object.keys(countries);
if (filter) {
sortedFiltered = sortedFiltered.filter(function(code) {
var country = countries[code];
var name = country.name.toLowerCase();
var lang = languages[country.lang].toLowerCase();
return name.indexOf(filter) !== -1 || lang.indexOf(filter) !== -1;
});
}
sortedFiltered.sort(function(a, b) {
var rankA = countryRanks.hasOwnProperty(a) ? countryRanks[a] : $defaultRank.val();
var rankB = countryRanks.hasOwnProperty(b) ? countryRanks[b] : $defaultRank.val();
if (rankA !== rankB) {
return rankA - rankB;
} else {
return countries[a].name.localeCompare(countries[b].name);
}
});
// Build list items
var defaultRank = $defaultRank.val();
sortedFiltered.forEach(function(code) {
var country = countries[code];
var name = country.name;
var lang = languages[country.lang];
var rankSpecified = countryRanks.hasOwnProperty(code);
var rank = rankSpecified ? countryRanks[code] : defaultRank;
// Create list item
var li = document.createElement('li');
li.dataset.code = code;
// Create list item content
var content = `
${name} (${lang})
<span class="controls">
<input type="checkbox" ${rankSpecified ? 'checked' : ''}/>
<input type="number" class="xxs" ${rankSpecified ? '' : 'disabled'} value="${rank}"/>
</span>
`;
// Append list item to fragment
li.innerHTML = content;
fragment.appendChild(li);
});
// Replace list content with fragment
$list.empty();
$list[0].appendChild(fragment);
}
function initFreelancerSettings()
{
var _default = countryRanks['_default']?countryRanks['_default']:0;
$('#countries .default-rank').val(_default);
updateCountryList();
$('#countries .filter').on('keyup', function()
{
updateCountryList();
});
$('#countries .list [type=number]').on('change', function()
{
updateCountryRankForElement(this);
updateCountryList();
});
$('#countries [type=checkbox]').on('change', function()
{
updateCountryRankForElement(this);
updateCountryList();
});
$('#countries .default-rank').on('change', function()
{
updateCountryList();
});
}