摘要: 在本教程中,您将学习如何使用原生 JavaScript 构建一个字数统计应用程序。
这是您将要构建的 字数统计应用程序。
创建项目结构
首先,创建名为 word-counter
的项目文件夹。
其次,在 word-counter
项目下,创建 css
和 js
文件夹,分别用于存储 CSS 和 JavaScript 文件。
第三,在 css
文件夹内创建一个 style.css
文件,并在 js
文件夹内创建两个名为 word-counter.js
和 app.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.count
Code language: HTML, XML (xml)
问题出现在 WordCounter
类的 count()
方法中

它显示 this.inputText
是 未定义的。因此,访问 this.inputText
的 value
属性会导致错误。
解决此问题
当 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
问题。