主页/index.php
var form = document.createElement("form");
form.id = "survey-form";
var elements = [
{
type: "select",
label: "Send to employee",
id: "empno",
options: [] // Options will be populated dynamically
},
];
elements.forEach(function (element) {
var wrapper;
var label = document.createElement("label");
label.className = "form-label";
label.textContent = element.label;
if (element.type === "select") {
input = document.createElement("select");
input.id = element.id;
input.className = "user-input";
form.appendChild(label);
form.appendChild(input);
fetchOptionsUsingWorker(input, element.options);
$(document).ready(function() {
$('#' + element.id).select2();
});
}
});
function fetchOptionsUsingWorker(selectElement) {
var worker = new Worker('optionsWorker.js');
worker.addEventListener('message', function(e) {
if (e.data.type === 'optionsData') {
var optionsData = e.data.data;
populateSelectWithOptions(selectElement, optionsData);
} else if (e.data.type === 'error') {
console.error('Error fetching options data:', e.data.message);
}
});
worker.postMessage('fetchOptions');
}
function populateSelectWithOptions(selectElement, optionsData) {
selectElement.innerHTML = '';
optionsData.forEach(function (option) {
var optionElement = document.createElement("option");
optionElement.value = option;
optionElement.text = option;
selectElement.appendChild(optionElement);
});
}
主页/optionsWorker.js
function fetchOptionsFromServer() {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("POST", "../backend.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onload = function () {
if (xhr.status === 200) {
var data;
if (xhr.responseText === "No data found") {
data = ["No data found"];
} else {
data = JSON.parse(xhr.responseText);
}
resolve(data);
} else {
reject(xhr.statusText);
}
};
var data = "input=get_options";
xhr.send(data);
});
}
self.addEventListener('message', async function(e) {
if (e.data === 'fetchOptions') {
try {
const optionsData = await fetchOptionsFromServer();
self.postMessage({ type: 'optionsData', data: optionsData });
} catch (error) {
self.postMessage({ type: 'error', message: error });
}
}
});
由于从服务器获取了数千条数据,因此我使用 webworkers 来运行在后台线程中获取数据的代码,否则网页会一直冻结。但即使使用了 webworkers 后,也没有什么好处,因为网页仍然冻结。我哪里出错了?请指导我。
<select>
不起作用。基本上,您需要一个自定义下拉菜单并在其弹出窗口中添加一个虚拟滚动列表。具有相同行高的虚拟滚动非常容易实现(在本示例中没有单个项目偏移(简化)):
const arr = Array.from({length:70000}, () => Math.random());
unorderedList.style.height = (arr.length * 32) + 'px';
drawItems();
wrapper.addEventListener('scroll', drawItems);
function drawItems(){
debugger;
const pos = wrapper.scrollTop;
const from = pos / 32 | 0;
const to = from + wrapper.offsetHeight / 32 | 0 + 1;
unorderedList.innerHTML = arr.slice(from, to).map((item, idx) => `<li>${from + idx + 1}: ${item}</li>`).join('');
let top = -32;
[...unorderedList.children].forEach((li, idx) => li.style.top = `${top += 32}px`);
}
#wrapper{
max-height:100vh;
overflow:auto;
}
body{
margin:0;
padding:0;
overflow:hidden;
}
li{
position:absolute;
height:32px;
line-hieght:32px;
}
<div id="wrapper">
<ul id="unorderedList"></ul>
</div>