我正在做一个项目,我为这个项目创建了一个自定义下拉国际国家代码选择部分,为此我使用innerHTML注入了所有SVG标志图标,我注意到在使用了240行innerHTML之后,我的网站的性能/加载速度受到了innerHTML的负面影响。
- 请看我的JS代码-**
我也读了很多文章在互联网上,innerHTML是非常缓慢的,但我还没有找到任何替代innerHTML,你能请指导我一点我的JS代码,以提高我的应用程序的性能。
- 注意:**我也怀疑SVG旗帜图标是我的应用加载缓慢的真正罪魁祸首吗?因为它包含239个SVG旗帜图标。也许这个SVG图标需要时间在我的网页上渲染。如果这是真正的罪魁祸首,你能指导我优化代码以加快加载速度吗?
// Autoclick on the parent div to hide the Dropdown after loading a page (Bug)
window.addEventListener('load', () => {
document.querySelector(".country-code-selector").click();
});
document.addEventListener('DOMContentLoaded', () => {
const head = document.getElementsByTagName('head')[0];
const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'https://amitdutta.co.in/flag/css/flag-icon.css';
head.appendChild(link);
// Get dropdowns and form
const dropdowns = document.querySelectorAll('[cc-data-dropdown]');
const form = document.querySelector('.country-code-selector form');
// Check if dropdowns exist on page
if (dropdowns.length > 0) {
// Loop through dropdowns and create custom dropdown for each select element
dropdowns.forEach(dropdown => {
createCustomDropdown(dropdown);
});
}
// Check if form element exist on page
if (form !== null) {
// When form is submitted console log the value of the select field
form.addEventListener('submit', (e) => {
e.preventDefault();
console.log('Selected country:', form.querySelector('[name="country"]').value);
});
}
// Create custom dropdown
function createCustomDropdown(dropdown) {
// Get all options and convert them from nodelist to array
const options = dropdown.querySelectorAll('option');
const optionsArr = Array.prototype.slice.call(options);
optionsArr[0].innerHTML = '<span class="flag-icon flag-icon-afg"></span> Afganistan (+69)';
optionsArr[1].innerHTML = '<span class="flag-icon flag-icon-alb"></span> Albania (+355)';
optionsArr[2].innerHTML = '<span class="flag-icon flag-icon-dza"></span> Algeria (+213)';
optionsArr[3].innerHTML = '<span class="flag-icon flag-icon-asm"></span> American Samoa (+1-684)';
optionsArr[4].innerHTML = '<span class="flag-icon flag-icon-and"></span> Andorra (+376)';
optionsArr[5].innerHTML = '<span class="flag-icon flag-icon-ago"></span> Angola (+244)';
optionsArr[6].innerHTML = '<span class="flag-icon flag-icon-aia"></span> Anguilla (+1-264)';
optionsArr[7].innerHTML = '<span class="flag-icon flag-icon-ata"></span> Antarctica (+672)';
optionsArr[8].innerHTML = '<span class="flag-icon flag-icon-atg"></span> Antigua and Barbuda (+1-268)';
optionsArr[9].innerHTML = '<span class="flag-icon flag-icon-arg"></span> Argentina (+54)';
optionsArr[10].innerHTML = '<span class="flag-icon flag-icon-arm"></span> Armenia (+374)';
optionsArr[11].innerHTML = '<span class="flag-icon flag-icon-abw"></span> Aruba (+297)';
optionsArr[12].innerHTML = '<span class="flag-icon flag-icon-aus"></span> Australia (+61)';
optionsArr[13].innerHTML = '<span class="flag-icon flag-icon-aut"></span> Austria (+43)';
optionsArr[14].innerHTML = '<span class="flag-icon flag-icon-aze"></span> Azerbaijan (+994)';
optionsArr[15].innerHTML = '<span class="flag-icon flag-icon-bhs"></span> Bahamas (+1-242)';
optionsArr[16].innerHTML = '<span class="flag-icon flag-icon-bhr"></span> Bahrain (+973)';
optionsArr[17].innerHTML = '<span class="flag-icon flag-icon-bgd"></span> Bangladesh (+880)';
optionsArr[18].innerHTML = '<span class="flag-icon flag-icon-brb"></span> Barbados (+1-246)';
optionsArr[19].innerHTML = '<span class="flag-icon flag-icon-blr"></span> Belarus (+375)';
optionsArr[20].innerHTML = '<span class="flag-icon flag-icon-bel"></span> Belgium (+32)';
optionsArr[21].innerHTML = '<span class="flag-icon flag-icon-blz"></span> Belize (+501)';
optionsArr[22].innerHTML = '<span class="flag-icon flag-icon-ben"></span> Benin (+229)';
optionsArr[23].innerHTML = '<span class="flag-icon flag-icon-bmu"></span> Bermuda (+1-441)';
optionsArr[24].innerHTML = '<span class="flag-icon flag-icon-btn"></span> Bhutan (+975)';
optionsArr[25].innerHTML = '<span class="flag-icon flag-icon-bol"></span> Bolivia (+591)';
optionsArr[26].innerHTML = '<span class="flag-icon flag-icon-bih"></span> Bosnia and Herzegovina (+387)';
optionsArr[27].innerHTML = '<span class="flag-icon flag-icon-bwa"></span> Botswana (+267)';
optionsArr[28].innerHTML = '<span class="flag-icon flag-icon-bra"></span> Brazil (+55)';
optionsArr[29].innerHTML = '<span class="flag-icon flag-icon-iot"></span> British Indian Ocean Territory (+246)';
optionsArr[30].innerHTML = '<span class="flag-icon flag-icon-vgb"></span> British Virgin Islands (+1-284)';
optionsArr[31].innerHTML = '<span class="flag-icon flag-icon-brn"></span> Brunei (+673)';
optionsArr[32].innerHTML = '<span class="flag-icon flag-icon-bgr"></span> Bulgaria (+359)';
optionsArr[33].innerHTML = '<span class="flag-icon flag-icon-bfa"></span> Burkina Faso (+226)';
optionsArr[34].innerHTML = '<span class="flag-icon flag-icon-bdi"></span> Burundi (+257)';
optionsArr[35].innerHTML = '<span class="flag-icon flag-icon-khm"></span> Cambodia (+855)';
optionsArr[36].innerHTML = '<span class="flag-icon flag-icon-cmr"></span> Cameroon (+237)';
optionsArr[37].innerHTML = '<span class="flag-icon flag-icon-can"></span> Canada (+1)';
optionsArr[38].innerHTML = '<span class="flag-icon flag-icon-cpv"></span> Cape Verde (+238)';
optionsArr[39].innerHTML = '<span class="flag-icon flag-icon-cym"></span> Cayman Islands (+1-345)';
optionsArr[40].innerHTML = '<span class="flag-icon flag-icon-caf"></span> Central African Republic (+236)';
optionsArr[41].innerHTML = '<span class="flag-icon flag-icon-tcd"></span> Chad (+235)';
optionsArr[42].innerHTML = '<span class="flag-icon flag-icon-chl"></span> Chile (+56)';
optionsArr[43].innerHTML = '<span class="flag-icon flag-icon-chn"></span> China (+86)';
optionsArr[44].innerHTML = '<span class="flag-icon flag-icon-cxr"></span> Christmas Island (+61)';
optionsArr[45].innerHTML = '<span class="flag-icon flag-icon-cck"></span> Cocos Islands (+61)';
optionsArr[46].innerHTML = '<span class="flag-icon flag-icon-col"></span> Colombia (+57)';
optionsArr[47].innerHTML = '<span class="flag-icon flag-icon-com"></span> Comoros (+269)';
optionsArr[48].innerHTML = '<span class="flag-icon flag-icon-cok"></span> Cook Islands (+682)';
optionsArr[49].innerHTML = '<span class="flag-icon flag-icon-cri"></span> Costa Rica (+506)';
optionsArr[50].innerHTML = '<span class="flag-icon flag-icon-hrv"></span> Croatia (+385)';
optionsArr[51].innerHTML = '<span class="flag-icon flag-icon-cub"></span> Cuba (+53)';
optionsArr[52].innerHTML = '<span class="flag-icon flag-icon-cuw"></span> Curacao (+599)';
optionsArr[53].innerHTML = '<span class="flag-icon flag-icon-cyp"></span> Cyprus (+357)';
optionsArr[54].innerHTML = '<span class="flag-icon flag-icon-cze"></span> Czech Republic (+420)';
optionsArr[55].innerHTML = '<span class="flag-icon flag-icon-cod"></span> Democratic Republic of the Congo (+243)';
optionsArr[56].innerHTML = '<span class="flag-icon flag-icon-dnk"></span> Denmark (+45)';
optionsArr[57].innerHTML = '<span class="flag-icon flag-icon-dji"></span> Djibouti (+253)';
optionsArr[58].innerHTML = '<span class="flag-icon flag-icon-dma"></span> Dominica (+1-767)';
optionsArr[59].innerHTML = '<span class="flag-icon flag-icon-dom"></span> Dominican Republic (+1-809)';
optionsArr[60].innerHTML = '<span class="flag-icon flag-icon-tls"></span> East Timor (+670)';
optionsArr[61].innerHTML = '<span class="flag-icon flag-icon-ecu"></span> Ecuador (+593)';
optionsArr[62].innerHTML = '<span class="flag-icon flag-icon-egy"></span> Egypt (+20)';
optionsArr[63].innerHTML = '<span class="flag-icon flag-icon-slv"></span> El Salvador (+503)';
optionsArr[64].innerHTML = '<span class="flag-icon flag-icon-gnq"></span> Equatorial Guinea (+240)';
optionsArr[65].innerHTML = '<span class="flag-icon flag-icon-eri"></span> Eritrea (+291)';
optionsArr[66].innerHTML = '<span class="flag-icon flag-icon-est"></span> Estonia (+372)';
optionsArr[67].innerHTML = '<span class="flag-icon flag-icon-eth"></span> Ethiopia (+251)';
optionsArr[68].innerHTML = '<span class="flag-icon flag-icon-flk"></span> Falkland Islands (+500)';
optionsArr[69].innerHTML = '<span class="flag-icon flag-icon-fro"></span> Faroe Islands (+298)';
optionsArr[70].innerHTML = '<span class="flag-icon flag-icon-fji"></span> Fiji (+679)';
// More 169 Countries (Currently not added here) -
optionsArr[71].innerHTML = 'No Data Found';
// Create custom dropdown element and add class dropdown to it
// Insert it in the DOM after the select field
const customDropdown = document.createElement('div');
customDropdown.classList.add('cc-dropdown');
dropdown.insertAdjacentElement('afterend', customDropdown);
// Create element for selected option
// Add class to this element, text from the first option in select field and append it to custom dropdown
const selected = document.createElement('div');
selected.classList.add('cc-dropdown-selected');
selected.innerHTML = 'Tel-Code';
customDropdown.appendChild(selected);
// Create element for dropdown menu, add class to it and append it to custom dropdown
// Add click event to selected element to toggle dropdown menu
const menu = document.createElement('div');
menu.classList.add('cc-dropdown-menu');
customDropdown.appendChild(menu);
selected.addEventListener('click', toggleDropdown.bind(menu));
// Create serach input element
// Add class, type and placeholder to this element and append it to menu element
const search = document.createElement('input');
search.placeholder = 'Search Your Country...';
search.type = 'text';
search.classList.add('cc-dropdown-menu-search');
menu.appendChild(search);
// Create wrapper element for menu items, add class to it and append to menu element
const menuItemsWrapper = document.createElement('div');
menuItemsWrapper.classList.add('cc-dropdown-menu-items');
menu.appendChild(menuItemsWrapper);
// Loop through all options and create custom option for each option and append it to items wrapper element
// Add click event for each custom option to set clicked option as selected option
optionsArr.forEach(option => {
const item = document.createElement('div');
item.classList.add('cc-dropdown-menu-item');
item.dataset.value = option.value;
item.innerHTML = option.innerHTML;
menuItemsWrapper.appendChild(item);
item.addEventListener('click', setSelected.bind(item, selected, dropdown, menu));
});
// Add selected class to first custom option
// menuItemsWrapper.querySelector('div').classList.add('selected');
// Add input event to search input element to filter items
// Add click event to document element to close custom dropdown if clicked outside of it
// Hide original dropdown(select)
search.addEventListener('input', filterItems.bind(search, optionsArr, menu));
document.addEventListener('click', closeIfClickedOutside.bind(customDropdown, menu));
dropdown.style.display = 'none';
}
// Toggle dropdown
function toggleDropdown() {
// Check if dropdown is opened and if it is close it, otherwise open it and focus search input
if (this.offsetParent !== null) {
this.style.display = 'none';
} else {
this.style.display = 'block';
this.querySelector('input').focus();
}
}
// Set selected option
function setSelected(selected, dropdown, menu) {
// Get value and label from clicked custom option
const value = this.dataset.value;
const label = this.innerHTML;
// Change the text on selected element
// Change the value on select field
filterDate = /(<span\b[^<>]*><\/span>\s*)\w+(?:\s+\w+)*\s*\((\+[\d-]+)\)/g;
selected.innerHTML = label.replace(filterDate, `$1$2`);
dropdown.value = value;
// Close the menu
// Reset search input value
// Remove selected class from previously selected option and show all divs if they were filtered
// Add selected class to clicked option
menu.style.display = 'none';
menu.querySelector('input').value = '';
menu.querySelectorAll('div').forEach(div => {
if (div.classList.contains('selected')) {
div.classList.remove('selected');
}
if (div.offsetParent === null) {
div.style.display = 'block';
}
});
this.classList.add('selected');
}
// Filter items
function filterItems(itemsArr, menu) {
// Get all custom options
// Get the value of search input and convert it to all lowercase characters
// Get filtered items
// Get the indexes of filtered items
const customOptions = menu.querySelectorAll('.cc-dropdown-menu-items div');
const value = this.value.toLowerCase();
const filteredItems = itemsArr.filter(item => item.value.toLowerCase().includes(value));
const indexesArr = filteredItems.map(item => itemsArr.indexOf(item));
// Check if option is not inside indexes array and hide it and if it is inside indexes array and it is hidden show it
var options = itemsArr.length;
itemsArr.forEach(option => {
if (!indexesArr.includes(itemsArr.indexOf(option))) {
customOptions[itemsArr.indexOf(option)].style.display = 'none';
options -= 1;
if (options <= 0) {
customOptions[itemsArr.length - 1].style.display = 'block';
}
} else {
if (customOptions[itemsArr.indexOf(option)].offsetParent === null) {
customOptions[itemsArr.indexOf(option)].style.display = 'block';
}
}
});
}
// Close dropdown if clicked outside dropdown element
function closeIfClickedOutside(menu, e) {
if (e.target.closest('.cc-dropdown') === null && e.target !== this && menu.offsetParent !== null) {
menu.style.display = 'none';
}
}
});
.cc-dropdown-menu-items::-webkit-scrollbar-track {
background-color: #323757;
width: 2px;
}
.cc-dropdown-menu-items::-webkit-scrollbar {
background-color: #323757;
width: 14px;
}
.cc-dropdown-menu-items::-webkit-scrollbar-thumb {
background-color: #e8576f;
border: 4px solid #323757;
z-index: -1;
width: 2px;
min-height: 50px;
}
#phone-number {
width: calc(100% - 120px);
margin-left: 120px;
}
.frm div:nth-child(3) .inputBox .tx {
margin-left: 120px;
}
.frm div:nth-child(3) .inputBox {
display: flex;
}
.frm div:nth-child(3) .inputBox .ln {
margin-left: 120px;
width: calc(100% - 120px);
}
.cc-dropdown {
position: relative;
}
.cc-dropdown-selected {
display: flex;
align-items: center;
justify-content: center;
width: 116px;
height: 40px;
padding: 0 20px 0 10px;
position: relative;
cursor: pointer;
transition: box-shadow .3s ease;
background-color: #323757;
border-radius: 3px;
font-size: 15px;
color: #fff;
}
.cc-dropdown-selected::after {
top: calc(50% - 2px);
right: 10px;
border: solid transparent;
content: '';
height: 0;
width: 0;
position: absolute;
border-top-color:#000;
border-width: 4px;
margin-left: -4px;
}
.cc-dropdown-selected:hover {
box-shadow: 0 0 5px rgba(0,0,0,0.1);
}
.cc-dropdown-menu {
position: absolute;
top: 100%;
left: 0;
width: 273px;
border: 3px solid #323757;
margin-right: -2px;
border-top: 0;
background-color: #fff;
z-index: +9;
margin-top: 10px;
}
.cc-dropdown-menu-items {
max-height: 200px;
width: 270px;
overflow-y: auto;
overflow-x: hidden;
z-index: +9;
}
.cc-dropdown-menu-search {
display: block;
width: 270px;
border: 0;
border-right: 3px solid #323757;
padding: 14px 0px 14px 10px;
font-size: 15px;
font-weight: 550;
color: #fff;
outline: 0;
background-color: #323757;
}
.cc-dropdown-menu-search::placeholder {
color: rgb(214, 214, 214)!important;
}
.cc-dropdown-menu-item {
width: 267px;
border-bottom: 1px solid #323757a6;
font-size: 14px;
font-weight: 550;
cursor: pointer;
z-index: +9;
user-select: none;
padding: 10px 18px 10px 10px;
}
.cc-dropdown-menu-items .flag-icon {
height: 15px;
width: 26px;
margin-right: 3px;
}
.cc-dropdown-menu-item:last-child {
border-bottom: 0;
}
.cc-dropdown-menu-item:hover {
background-color: rgb(228, 228, 228);
}
.cc-dropdown-menu-item.selected {
border: none;
}
.cc-dropdown-selected .flag-icon {
margin-right: 5px!important;
}
.cc-dropdown-menu-item.selected, .cc-dropdown-menu-item.selected:hover {
background-color: #323757c2;
color: #ffffff;
}
.cc-dropdown-menu-item:last-child {
pointer-events: none;
}
<div class="country-code-selector">
<form class="cc-form">
<div class="cc-form-group">
<select id="country" name="country" cc-data-dropdown>
<option value="Afganistan"></option>
<option value="Albania"></option>
<option value="Algeria"></option>
<option value="American Samoa"></option>
<option value="Andorra"></option>
<option value="Angola"></option>
<option value="Anguilla"></option>
<option value="Antarctica"></option>
<option value="Antigua and Barbuda"></option>
<option value="Argentina"></option>
<option value="Armenia"></option>
<option value="Aruba"></option>
<option value="Australia"></option>
<option value="Austria"></option>
<option value="Azerbaijan"></option>
<option value="Bahamas"></option>
<option value="Bahrain"></option>
<option value="Bangladesh"></option>
<option value="Barbados"></option>
<option value="Belarus"></option>
<option value="Belgium"></option>
<option value="Belize"></option>
<option value="Benin"></option>
<option value="Bermuda"></option>
<option value="Bhutan"></option>
<option value="Bolivia"></option>
<option value="Bosnia and Herzegovina"></option>
<option value="Botswana"></option>
<option value="Brazil"></option>
<option value="British Indian Ocean Territory"></option>
<option value="British Virgin Islands"></option>
<option value="Brunei"></option>
<option value="Bulgaria"></option>
<option value="Burkina Faso"></option>
<option value="Burundi"></option>
<option value="Cambodia"></option>
<option value="Cameroon"></option>
<option value="Canada"></option>
<option value="Cape Verde"></option>
<option value="Cayman Islands"></option>
<option value="Central African Republic"></option>
<option value="Chad"></option>
<option value="Chile"></option>
<option value="China"></option>
<option value="Christmas Island"></option>
<option value="Cocos Islands"></option>
<option value="Colombia"></option>
<option value="Comoros"></option>
<option value="Cook Islands"></option>
<option value="Costa Rica"></option>
<option value="Croatia"></option>
<option value="Cuba"></option>
<option value="Curacao"></option>
<option value="Cyprus"></option>
<option value="Czech Republic"></option>
<option value="Democratic Republic of the Congo"></option>
<option value="Denmark"></option>
<option value="Djibouti"></option>
<option value="Dominica"></option>
<option value="Dominican Republic"></option>
<option value="East Timor"></option>
<option value="Ecuador"></option>
<option value="Egypt"></option>
<option value="El Salvador"></option>
<option value="Equatorial Guinea"></option>
<option value="Eritrea"></option>
<option value="Estonia"></option>
<option value="Ethiopia"></option>
<option value="Falkland Islands"></option>
<option value="Faroe Islands"></option>
<option value="Fiji"></option>
<option></option>
</select>
</div>
</form>
</div>
1条答案
按热度按时间wljmcqd81#
每次赋值给
.innerHTML
时,整个DOM都要重新渲染,所以不要分别赋值给每个<option>
,创建一个包含所有选项的字符串,然后一次性赋值给<select>
的.innerHTML
。