【问题标题】:jQuery "keyup" crashing page when checking 'Word Count'检查'字数'时jQuery“keyup”崩溃页面
【发布时间】:2013-11-14 06:37:16
【问题描述】:

我有一个在 DIV 上运行的单词计数器,在输入几个单词后,页面崩溃了。浏览器继续工作(标准滚动),Chrome 的控制台中没有显示任何错误。不知道哪里出错了……

这一切都是从我在“keyup”中传递“wordCount(q);”开始的。我只是将它传递到那里,因为它会拆分出“NaN”而不是倒计时的数字。

JS:

wordCount();

$('#group_3_1').click(function(){
    var spliced = 200;
    wordCount(spliced);
}) ;

$('#group_3_2').click(function(){
    var spliced = 600;
    wordCount(spliced);
}) ;

function wordCount(q) {
    var content_text = $('.message1').text(),
        char_count = content_text.length;

        if (char_count != 0) 
          var word_count = q - content_text.replace(/[^\w ]/g, "").split(/\s+/).length;
        $('.word_count').html(word_count + " words remaining...");

        $('.message1').keyup(function() {
          wordCount(q);
        });

        try
        {
            if (new Number( word_count ) < 0) {
                $(".word_count").attr("id","bad");
            }
            else {
                $(".word_count").attr("id","good");
            }
        } catch (error)
        {
            //
        }

  };

HTML:

<input type="checkbox" name="entry.3.group" value="1/6" class="size1" id="group_3_1">
<input type="checkbox" name="entry.3.group" value="1/4" class="size1" id="group_3_2">


<div id="entry.8.single" class="message1" style="height: 400px; overflow-y:scroll; overflow-x:hidden;" contenteditable="true"> </div>
<span class="word_count" id="good"></span>

提前致谢!

【问题讨论】:

  • 你的 wordCount() 函数在哪里?
  • 只是一个疑问..你为什么要在 wordCount() 函数中注册 keyup?
  • keyup 事件在内容可编辑元素中触发时,您正在运行一个无限循环 - 这就是浏览器崩溃的原因。
  • 如果用户没有点击任何复选框怎么办? word_count 的默认值是多少?

标签: javascript jquery html performance


【解决方案1】:

这导致了无限循环if (new Number(word_count) &lt; 0) {

您的代码完全是一团糟。只需学习并从更基本的概念开始,然后重新开始。如果您想在评论中向我描述您的项目,我很乐意向您展示一种好的、干净、易读的方法。

更新:
在代码中拥有良好架构的一部分是将逻辑的不同部分分开。您的代码的任何部分都不应该知道或使用与它不直接相关的任何内容。请注意,在我的单词计数器中,它所做的任何事情都与它的单词计数器直接相关。单词计数器是否关心计数会发生什么?没有。它只是计算并将结果发送出去(无论你告诉它到哪里,通过回调函数)。这不是唯一的方法,但我只是想让您了解如何更明智地处理事情。

Live demo here (click).

/* what am I creating? A word counter.
 * How do I want to use it?
 * -Call a function, passing in an element and a callback function
 * -Bind the word counter to that element
 * -When the word count changes, pass the new count to the callback function
 */

window.onload = function() {
  var countDiv = document.getElementById('count');
  wordCounter.bind(countDiv, displayCount);
  //you can pass in whatever function you want. I made one called displayCount, for example
};

var wordCounter = {
  current : 0,
  bind : function(elem, callback) {
    this.ensureEditable(elem);
    this.handleIfChanged(elem, callback);

    var that = this;
    elem.addEventListener('keyup', function(e) {
      that.handleIfChanged(elem, callback);
    });
  },
  handleIfChanged : function(elem, callback) {
    var count = this.countWords(elem);
    if (count !== this.current) {
      this.current = count;
      callback(count);
    }
  },
  countWords : function(elem) {
    var text = elem.textContent;
    var words = text.match(/(\w+\b)/g);
    return (words) ? words.length : 0;
  },
  ensureEditable : function(elem) {
    if (
      elem.getAttribute('contenteditable') !== 'true' && 
      elem.nodeName !== 'TEXTAREA' &&
      elem.nodeName !== 'INPUT'
    ) {
      elem.setAttribute('contenteditable', true); 
    }
  }
};

var display = document.getElementById('display');
function displayCount(count) {
  //this function is called every time the word count changes
  //do whatever you want...the word counter doesn't care.
  display.textContent = 'Word count is: '+count;
}

【讨论】:

  • 嗨@m59,我在处理函数之外的变量方面还是有点新意。它实际上是在 Stack Overflow 上找到的 2 个代码段的组合。当我拆分代码以便通过选择一个复选框给出变量时,那就是它变得有点混乱并且使用现有代码并没有帮助我猜!
  • 你需要停止复制别人的代码,特别是如果你不理解它。在你调试这个烂摊子的时间里,你本可以学会编写比你复制的代码更好的代码。我正在更新我的答案..我认为这会对您有所帮助。 @MichaelMarchment
【解决方案2】:

我可能会这样做

http://jsfiddle.net/6WW7Z/2/

var wordsLimit = 50;

$('#group_3_1').click(function () {
    wordsLimit = 200;
    wordCount();
});
$('#group_3_2').click(function () {
    wordsLimit = 600;
    wordCount();
});
$('.message1').keydown(function () {
    wordCount();
});

function wordCount() {
    var text = $('.message1').text(),
        textLength = text.length,
        wordsCount = 0,
        wordsRemaining = wordsLimit;

    if(textLength > 0) {
        wordsCount = text.replace(/[^\w ]/g, '').split(/\s+/).length;
        wordsRemaining = wordsRemaining - wordsCount;
    }
    $('.word_count')
        .html(wordsRemaining + " words remaining...")
        .attr('id', (parseInt(wordsRemaining) < 0 ? 'bad' : 'good'));

};  

wordCount();

它并不完美和完整,但它可能会向您展示如何做到这一点。如果选中/未选中,您应该在复选框上使用更改事件来更改 wordsLimit。对于有效/无效剩余字数消息的样式,请使用类而不是 id。

【讨论】:

  • 您应该使用按键功能上的事件来测试某个键。
  • 非常感谢@f1ames !!究竟是什么。非常感谢您的快速回复:)
【解决方案3】:

我认为您应该使用radio 代替checkboxes,因为您一次只能限制200600

试试这个,

wordCount();
$('input[name="entry.3.group"]').click(function () {
    wordCount();
    $('.word_count').html($(this).data('val') + " words remaining...");
});
$('.message1').keyup(function () {
    wordCount();    
});

function wordCount() {
    var q = $('input[name="entry.3.group"]:checked').data('val');
    var content_text = $('.message1').text(),
        char_count = content_text.length;
    if (char_count != 0) var word_count = q - content_text.replace(/[^\w ]/g, "").split(/\s+/).length;
    $('.word_count').html(word_count + " words remaining...");
    try {
        if (Number(word_count) < 0) {
            $(".word_count").attr("id", "bad");
        } else {
            $(".word_count").attr("id", "good");
        }
    } catch (error) {
        //
    }    
};

如果你的spanbad id 那么你也可以添加key up 应该return false;

Demo

【讨论】:

  • 这实际上是一个合乎逻辑的快速解决方案!哈哈。我正在使用由客户创建的谷歌文档,所以我会考虑改变它。干杯@rohan-kumar
猜你喜欢
  • 2013-06-17
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多