JavaScript 字数统计器

摘要: 在本教程中,您将学习如何使用原生 JavaScript 构建一个字数统计应用程序。

这是您将要构建的 字数统计应用程序

创建项目结构

首先,创建名为 word-counter 的项目文件夹。

其次,在 word-counter 项目下,创建 cssjs 文件夹,分别用于存储 CSS 和 JavaScript 文件。

第三,在 css 文件夹内创建一个 style.css 文件,并在 js 文件夹内创建两个名为 word-counter.jsapp.js 的 JavaScript 文件。

最后,在项目根文件夹中创建 index.html 文件。

最终的项目文件夹结构将如下所示

创建 HTML 文件

首先,编辑 index.html 文件并将 CSS 和 JavaScript 文件放入 index.html 文件中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript Word Counter</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
   
    <script src="js/word-counter.js"></script>
    <script src="js/app.js"></script>
</body>
</html>Code language: HTML, XML (xml)

WordCounter 应用程序将有一个简单的 <textarea> 元素。当您输入一些文本时,它将显示您输入的字符和单词数量。

为此,您需要有 <textarea><div> 元素

  • <textarea> 元素将允许您输入文本。
  • <div> 元素将显示输入到 <textarea> 元素中的字符和单词数量。

默认情况下,<div> 元素应该显示 0 个字符和 0 个单词。

其次,在 <body> 标签打开后和第一个 <script> 标签之前,将 <textarea><div> 元素添加到 index.html 文件中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript Word Counter</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
   
<h1>Word Counter</h1>
    <label for="text">Enter some text below:</label>
    <textarea id="text" rows="10" cols="60"></textarea>
    <div id="stat">You've written 0 words and 0 characters.</div>
    <script src="js/word-counter.js"></script>
    <script src="js/app.js"></script>
</body>
</html>Code language: HTML, XML (xml)

创建 WordCounter 类

首先,您将在 word-counter.js 文件中创建 WordCounter

class WordCounter {
}Code language: JavaScript (javascript)

WordCounter 类将接受一个 <textarea> 元素。它将监听 <textarea> 元素的 input 事件,并计算 <textarea> 元素包含的字符和单词数量。

其次,将 constructor 添加到 WordCounter 类中。constructor 将接受一个 <textarea> 元素。

constructor 中,您将类的 inputText 属性初始化为 inputText 参数,并将 input 事件监听器附加到 inputText 元素

class WordCounter {
    constructor(inputText) {
        this.inputText = inputText;
        this.inputText.addEventListener('input', this.count);
    }
    count(){
    }
}Code language: JavaScript (javascript)

this.count() 方法将在每次 input 事件发生时执行。稍后我们将回到实现 count() 方法的逻辑。

第三,向 WordCounter 类添加一个新方法,该方法计算字符和单词的数量

class WordCounter {
    constructor(inputText) {
        this.inputText = inputText;
        this.inputText.addEventListener('input', this.count);
    }
    count(){
    }
    getWordStat(str) {
        let matches = str.match(/\S+/g);
        return {
            characters: str.length,
            words: matches ? matches.length : 0,
        };
    }
}Code language: JavaScript (javascript)

getWordStat() 方法使用 正则表达式 /\S/g 返回字符串的单词数量。它还使用输入字符串 str 的字符串 length 属性来获取字符数量。

第三,count() 方法需要调用 getWordStat() 来计算 inputText 元素的单词和字符数量。

要获取 <textarea> 元素的文本,您使用它的 value 属性

...
count() {
   let wordStat = this.getWordStat(this.inputText.value.trim());
   // how to expose the wordStat to the outside
   // ..
}Code language: JavaScript (javascript)

count() 方法还需要与外部通信单词和字符的数量。

为此,您有两个选择:使用 回调自定义事件。在本教程中,我们将使用 自定义事件

如果您想知道如何使用回调,请查看 倒计时器教程

第四,向 WordCounter 类添加一个名为 emitEvent 的新方法

emitEvent(wordStat) {
        // Create count event
        let countEvent = new CustomEvent('count', {
            bubbles: true,
            cancelable: true,
            detail: {
                wordStat
            }
        });
        // dispatch the count event
        this.inputText.dispatchEvent(countEvent);
}Code language: JavaScript (javascript)

emitEvent() 方法接受一个 wordStat 对象。在方法内部,我们使用 CustomEvent 构造函数为 inputText 元素创建一个名为 count 的自定义事件,并使用 dispatchEvent 方法分派 count 事件。

稍后,您将为 count 事件附加一个事件监听器,并使用 event.detail.wordStat 语法访问 wordStat 对象。

emitEvent() 应该在每次 input 事件发生时被调用。因此,我们在 count() 方法中调用 emitEvent()

count(){
   let wordStat = this.getWordStat(this.inputText.value.trim());
   this.emitEvent(wordStat);
}Code language: JavaScript (javascript)

WordCounter 类将如下所示

class WordCounter {
    constructor(inputText) {
        this.inputText = inputText;
        this.inputText.addEventListener('input', this.count);
    }
    count(){
        let wordStat = this.getWordStat(this.inputText.value.trim());
        this.emitEvent(wordStat);
    }

    emitEvent(wordStat) {
        // Create count event
        let countEvent = new CustomEvent('count', {
            bubbles: true,
            cancelable: true,
            detail: {
                wordStat
            }
        });
        // dispatch the count event
        this.inputText.dispatchEvent(countEvent);

    }
    getWordStat(str) {
        let matches = str.match(/\S+/g);
        return {
            characters: str.length,
            words: matches ? matches.length : 0,
        };
    }
}Code language: JavaScript (javascript)

向 app.js 文件添加逻辑

首先,使用 querySelector() 方法选择 <textarea><div> 元素

const inputText = document.querySelector('#text');
const statElem = document.querySelector('#stat');
Code language: JavaScript (javascript)

其次,创建一个新的 WordCounter 类实例,并将 inputText 元素传递到它的构造函数中

new WordCounter(inputText);Code language: JavaScript (javascript)

第三,定义一个名为 render() 的新函数,该函数将单词和字符计数更新到 statElem 元素。

render() 函数接受一个自定义事件对象

const render = (event) => {
    statElem.innerHTML = `<p>You've written <span class="highlight">${event.detail.wordStat.words} words</span> 
        and <span class="highlight">${event.detail.wordStat.characters} characters</span>.</p>`;
}
Code language: HTML, XML (xml)

第四,为 count 事件添加一个事件监听器,并在每次 count 事件发生时执行 render() 方法

inputText.addEventListener('count', render);Code language: JavaScript (javascript)

app.js 将如下所示

const inputText = document.querySelector('#text');
const statElem = document.querySelector('#stat');

// create a new instance of WordCounter
new WordCounter(inputText);


const render = (event) => {
    statElem.innerHTML = `<p>You've written <span class="highlight">${event.detail.wordStat.words} words</span> 
        and <span class="highlight">${event.detail.wordStat.characters} characters</span>.</p>`;
}

inputText.addEventListener('count', render);Code language: JavaScript (javascript)

现在,如果您在 Web 浏览器中打开 index.html 文件,您将看到以下错误

Uncaught TypeError: Cannot read property 'value' of undefined at HTMLTextAreaElement.countCode language: HTML, XML (xml)

问题出现在 WordCounter 类的 count() 方法中

它显示 this.inputText未定义的。因此,访问 this.inputTextvalue 属性会导致错误。

解决此问题

inputText 元素上发生 input 事件时,count() 方法将执行。

执行 count() 方法的对象是 inputText 对象,而不是 WordCounter 类的实例。

这意味着在 count() 方法内部,this 值引用 inputText 元素,而不是 WordCounter 对象。

为了证明这一点,您可以将 this 值记录到 count() 方法中,如下所示

count() {
    console.log(this); 
}Code language: JavaScript (javascript)

… 然后刷新 index.html,您将在每次在 <textarea> 中输入一些文本时在控制台中看到 <textarea> 元素

<textarea id="text" rows="10" cols="60"></textarea>
Code language: HTML, XML (xml)

由于 count() 方法内部的 this 值引用 <textarea> 元素,因此它没有 inputText 属性。它也没有 emitEvent() 方法。

要解决此问题,您需要将事件监听器更改为 箭头函数,如下所示

constructor(inputText) {
   this.inputText = inputText;
    this.inputText.addEventListener('input', () => {
        this.count();
    });
}Code language: JavaScript (javascript)

当您使用箭头函数时,this 值将引用周围块的对象,在本例中是 WordCounter。换句话说,您可以在 count() 方法中访问 WordCounter 的所有属性和方法。

最终的 WordCounter 类将如下所示

class WordCounter {
    constructor(inputText) {
        this.inputText = inputText;
        this.inputText.addEventListener('input', () => {
            this.count();
        });
    }
    count() {
        let wordStat = this.getWordStat(this.inputText.value.trim());
        this.emitEvent(wordStat);
    }

    emitEvent(wordStat) {
        // Create count event
        let countEvent = new CustomEvent('count', {
            bubbles: true,
            cancelable: true,
            detail: {
                wordStat
            }
        });
        // dispatch the count event
        this.inputText.dispatchEvent(countEvent);

    }
    getWordStat(str) {
        let matches = str.match(/\S+/g);
        return {
            characters: str.length,
            words: matches ? matches.length : 0,
        };
    }
}Code language: JavaScript (javascript)

单击此处查看 Word Counter 应用程序的实际操作。

总结

在本教程中,您学习了如何使用原生 JavaScript 开发一个 Word Counter 应用程序。以下是主要要点

  • 如何创建和发出自定义事件。
  • 如何使用箭头函数解决 this 问题。
本教程是否有帮助?