3

想象一下,我们有一个文本字段,它在每个 keydown 事件上执行以下代码:

if( $('#my_input').val() == '' )
  $('#my_span').html('my input is blank');
else
  $('#my_span').html('My input is not blank');

显然,我们正在执行的代码可能会将某物(#my_span元素)的状态设置为它已经存在的状态,这似乎效率低下。但我很好奇替代方案是什么?添加更多检查,例如:

if ( $('#my_input').val() == '' ){
  if ( $('#my_span').html() != 'my input is blank' )
       $('#my_span').html('my input is blank');
}
else if ( $('#my_span').html() != 'My input is not blank' )
          $('#myspan').html('My input is not blank');

后者效率更高吗?在我看来,这似乎更“正确”,但显然它是更多代码,我不确定它比第一个示例效率多少。

我知道前者总是涉及 DOM 操作,这将影响计算相对效率,但我以前在非 DOM 相关代码中遇到过这样的情况,所以想知道在所有情况下最好的方法是什么。在将某项设置为新值之前,您是否应该始终对某项的值进行额外检查?

编辑:

我的最终版本实际上使用了这里的答案组合,因此感谢所有人的出色回复。总而言之,我现在:

  • 在闭包中缓存 jquery 对象
  • 使用状态来确定分配给新状态

顺便说一句,keydown 上的 setTimeout 是立即获取输入字段值的一种非常好的方法。再次感谢。

4

7 回答 7

7

我会缓存 jQuery 对象并使用布尔值来存储状态,而不是html在您不需要时调用:

(function(){
   var i = $('#my_input'), s=$('#my_span'), blank, check = function() {
      if (i.val()=='') {
         if (blank!==true) s.html('my input is blank');
         blank = true;
      } else {
         if (blank!==false) s.html('my input is not blank');
         blank = false;
      }
   };
   i.keyup(check);
   check(); // so that the span is initially filled
})();

请注意,您需要的不是keydownbut keyup,因此输入的值在您获得事件之前已更改。

于 2013-06-04T17:19:12.993 回答
4

如果您继续按下该键,此方法甚至可以工作;)

表现?去纯 JS。小提琴

//before event binding
var my_input = document.getElementById('my_input'),
  my_span = document.getElementById('my_span');

$(my_input).on('keydown', function () {
  //inside event handler
  var value = my_input.value
  , prevVal = my_input.prevVal
  ;

  if (value && prevVal && prevVal !== value) {
    return;
  }

  //timeout to return event handler execution early 
  //(ie: differ DOM manipulation from the event handler. 
  //So, UX will extra smooth ;) )
  setTimeout(function () {
    fieldStatusUpdater(my_input.value);
  }, 1);

});

function fieldStatusUpdater(value) {
  if (my_input.value === '') {
    my_span.innerHTML = 'my input is blank';
  } else {
    my_span.innerHTML = 'My input is not blank';
  }
  my_input.prevVal = value;
}

于 2013-06-04T17:20:52.440 回答
4

这是我能想到的最快最好的:

function keyUpEvent(){
    var state = null,
        input = $('#my_input'),
        span = $('#my_span');

    return function(){
        var test = input.val() === '';
        if( test === state) return;
        if(test)
          span.html('my input is blank');
        else
          span.html('My input is not blank');
        state = test;
    }
}
$('#my_input').keyup(keyUpEvent());

http://jsfiddle.net/TMb8T/

这使用闭包在初始化后存储输入和跨度元素。而且您可以(几乎)像使用普通功能一样使用它,因此您可以绑定它执行多个事件并且它仍然有效。请注意,您必须keyUpEvent在绑定事件时执行。

加法: 您现在还可以执行以下操作:

function keyUpEvent(input, span){
    var state = null;

    return function(){
        var test = input.val() === '';
        if( test === state) return;
        if(test)
            span.html('My input is blank');
        else
            span.html('My input is not blank');
        state = test;
    }
}


$('#my_input').keyup( keyUpEvent($('#my_input'), $('#my_span')) );
$('#my_input2').keyup( keyUpEvent($('#my_input2'), $('#my_span2')) );

http://jsfiddle.net/TMb8T/2/

像这样,您可以使用一个事件处理程序轻松检查整个表单的每个输入。

附加 2:如果您想让第 2 版即使在按键被按下的情况下也能正常工作;)

替换这个:

$('#my_input').keyup( keyUpEvent($('#my_input'), $('#my_span')) );

有了这个:

$('#my_input').keydown(function(){
    setTimeout(keyUpEvent($('#my_input'), $('#my_span')),1);
});

http://jsfiddle.net/TMb8T/4/

于 2013-06-04T17:37:17.747 回答
3

这实际上取决于您执行代码的频率。如果它仅在用户按下按钮或类似的东西时执行,则可以使用第一个按钮,它会在快速计时器上运行,然后可能不会。

这样做:

var text;
if ( $('#my_input').val() == '' )
    text = 'my input is blank';
else 
    text = 'My input is not blank';

if ( $(#my_span).html() != text )
    $('#my_span').html(text);
于 2013-06-04T17:19:58.883 回答
1

你可以用三元简化它

$('#my_span').html( $('#my_input').val() == '' ? 'my input is blank' : 'My input is not blank' );

更具可读性

var text = $('#my_input').val() == '' ? 'my input is blank' : 'My input is not blank';
$('#my_span').html(text);

如果你关心速度,它就会出现比阅读内容更快的 DOM 重绘。这真的取决于页面结构/大小,浏览器。如果您想查看通过 1000 次迭代可以节省多少毫秒,那么 JSPerf 是您的朋友。如果您发现性能问题,您真的应该寻找最快的。

  1. 没有检查,写内容
    • 如果数据更改或未更改,您将受到更新 DOM 的惩罚
  2. 检查,写作内容
    • 你有阅读 HTML 的惩罚
    • 你有更新 DOM 的惩罚
  3. 检查,无需写入
    • 你有阅读 HTML 的惩罚

现在 HTML 最有可能是不同的还是相同的等等?

解决方案取决于您想要做什么。缓存 jQuery 元素将加快查找/写入速度。它会比写入慢。

于 2013-06-04T17:17:44.043 回答
1

在里面:

var isBlank = true;

$('#my_span').html('my input is blank');

键位:

if(!isBlank){
    if( $('#my_input').val().length == 0){
        isBlank = true;
        $('#my_span').html('my input is blank');
    }
} else {
    if($('#my_input').val().length){
        isBlank = false;
        $('#my_span').html('my input is not blank');
    }
}

这样,您仅在状态更改时才操作 DOM。

此外,测试长度属性实际上可能比针对“”测试字符串更快,因为解释器不必从字符串文字创建 String 对象。

于 2013-06-04T17:23:23.820 回答
-1

如何将当前值保存到变量中,然后测试变量以查看是否必须更改它。除非您需要更改它,否则不要弄乱 DOM。(您也可以isBlank在这里使用一个名为的布尔值来获得良好的效果):

var currValue;
if ( $('#my_input').val() == '' ) {
  if ( currValue != 'my input is blank' ) {
       currValue = 'my input is blank';
       $('#my_span').html(currValue);
  }
} else if ( currValue != 'My input is not blank' ) {
       currValue = 'My input is not blank';
       $('#my_span').html(currValue);
}

您还提到这是在 keydown 事件处理程序中。

  1. 不要忘记在开始时运行一次此代码,以便将显示字段设置为显示输入字段为空白。
  2. 不要忘记用户可以选择文本并右键单击以选择“剪切”并清空该字段或选择“粘贴”以将文本添加到该字段。类似地,拖放操作可以添加或删除文本。

替代思路

使用定期检查的定时事件可能会更好。有些人每秒可以键入 3 到 4 个按键。如果您将其定时为每 1 秒查看一次该字段,则可以减少由于此代码运行而导致的短期减速,并将其替换为长期持续使用 CPU 周期。但是请记住,如果计算机没有做任何有趣的事情,就没有理由不使用 CPU 周期。

于 2013-06-04T17:17:20.087 回答