我有很多这样的输入,用户输入值:
<INPUT TYPE=TEXT NAME="Milk" ONKEYUP="convcase(document.convert.Milk.value)">
<INPUT TYPE=TEXT NAME="Buckwheat" ONKEYUP="convcase(document.convert.Buckwheat.value)">
和很多像这样的计算:
document.convert.Fe.value = BuckwheatFe * document.convert.Buckwheat.value + PeaFe * document.convert.Pea.value + MilkFe * document.convert.Milk.value + ...
document.convert.Hexadecanoic.value = BuckwheatHexadecanoic * document.convert.Buckwheat.value + PeaHexadecanoic * document.convert.Pea.value + MilkHexadecanoic * document.convert.Milk.value + ...
因此计算后的结果是动态显示的,当程序有数百种产品时,输入和计数之间的延迟太大。我计算所有产品:牛奶,荞麦......即使用户没有输入它们的价值。
你能告诉我如何修改算法以减少延迟吗?
答案 0 :(得分:1)
我会接近以下内容。需要在计算中使用的输入可以用类表示,例如&#34; itemValue&#34;,然后检索一次然后缓存。这假设他们不会改变。
标记可能如下所示:
<form name="convert">
Milk: <input class="itemValue" name="Milk" onkeyup="convcase(this)"><br>
Buckwheat: <input class="itemValue" name="Buckwheat" onkeyup="convcase(this)"><br>
Fe value: <input name="Fe"><br>
Hex value: <input name="Hexadecanoic"><br>
</form>
Fe和Hexadecanoic值之类的东西也可以缓存。如果将节点集合转换为数组以便可以使用内置数组函数,它也会有所帮助。这些可能比使用for循环慢,所以如果它们是,则将 reduce 调用转换为循环。
// Helper to convert a NodeList to an array so built-in methods can be used
function toArray(list) {
var i = list.length, arr = [];
while (i--) {
arr[i] = list[i];
}
return arr;
}
执行实际工作的功能:
var convcase = (function() {
// Cache stuff in a closure. Note that the names of each factor set
// must match the form control name where the related total is written
var factors = {
Fe: {Buckwheat:0.5, Milk:0.75},
Hexadecanoic: {Buckwheat:0.6, Milk:0.82}
};
var nodes;
return function (el) {
// Only get nodes the first time, assumes they don't change, and convert to Array
// This can be done before validation as it's not dependent on it
nodes = nodes || toArray(el.form.querySelectorAll('input.itemValue'));
// Validate el.value here and deal with invalid values.
// Only proceed if it's a valid value
// For each set of factors, do all the calculations and write totals to form
for (var factor in factors) {
// Get the factor set
var set = factors[factor];
// Write the total to the related form control
el.form[factor].value = nodes.reduce(function(sum, node){
sum += node.value * set[node.name];
return sum;
}, 0);
}
};
}());
我不会在keyup上执行此操作,我等待更改或模糊事件,因此只有在用户很有可能暂时完成计算时才会进行计算,否则可能会有很多无用的计算。
答案 1 :(得分:0)
将元素存储在数组中并使用循环。您还可以存储先前的值(旧的一个在其他数组中),并在执行计算之前将旧值与新值进行比较。如果值已更改,则只执行此操作。
答案 2 :(得分:0)
我知道一种处理此问题的标准方法。关键是:您不希望每个按键都触发算法。你想等待客户端停止输入(暂时);然后你触发算法。
(编辑:顺便说一下,请阅读下面的评论。你可能只是通过更改&#34; onkeyup&#34; by&#34; onchange&#34;)来帮助你。
使用clearTimeout / setTimeout组合,您可以做到这一点。我设定了打字时间&#39;到400毫秒,随意改变这个值。
<script>
var timer = null;
var interval = 400; // feel free to change this value
function imputChanged(elm) {
// if any previous key stroke happend less than 400ms ago; clearTimeout will cancel that request.
// only the last request will trigger executeAlgorithm().
clearTimeout(timer);
timer = setTimeout(function() {
executeAlgorithm(elm);
},
interval
);
}
function executeAlgorithm(elm) {
// do what ever you have to do here. As an example, I show the value in a div
document.getElementById('messages').innerHTML = elm.value;
}
</script>
<input onkeyup="imputChanged(this)">
<div id="messages"></div>
(编辑:看起来onkeyup在IE上的效果比onimput好;我现在将触发器设置为onkeyup)