摘要: 在本教程中,您将学习如何使用原生 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.countCode 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问题。