基于TypeScript的简易网页计算器

在本文中,将探讨如何使用TypeScript创建一个简单的网页计算器。这个计算器将展示TypeScript如何与网页内容进行交互。在开发过程中,将展示如何在TypeScript中使用“传统”JavaScript风格的函数。

正如往常一样,本文的代码可以在GitHub上找到。

设计思路

想要限制计算器的输入,使得按钮的点击仅限于一组已知的输入。基本上,希望每个按钮要么触发一个数字,要么触发某个描述的运算符。为了选择要使用的运算符,决定创建一个名为calculator.ts的TypeScript文件,并在其中添加一个Operator枚举。将这个文件添加到了解决方案的根目录。

enum Operator { add = '+', subtract = '-', multiply = '*', divide = '/', period = '.' }

在展示计算器的TypeScript代码之前,让先设置HTML页面。

<!DOCTYPE html> <html> <head> <title>100 Days of TypeScript - Calculator</title> </head> <body> <table border="1"> <th colspan="4"> <input id="display"> </th> </table> <script src="scripts/calculator.js"></script> </body> </html>

这里是一个HTML页面,显示了一个带有标题行的表格,标题行有4列宽,将显示任何计算的结果。还添加了一个script标签来加载计算器脚本。会注意到,尽管计算器TypeScript文件的源代码在根文件夹中,但src指向的是scripts文件夹。为了使TypeScript写入这个文件夹,需要调整tsconfig.json文件。

{ "compilerOptions": { "lib": ["DOM", "ES2015"], "outDir": "./scripts", "strict": true, "noUnusedLocals": true } }

这些条目中有两件事非常有趣。outDir键是设置输出目录的地方;这就是如何将calculator.js文件写入scripts目录的。lib条目也很有趣,因为在那里添加了一个DOM条目。当在lib中指定条目时,在告诉TypeScript它需要引入哪些库,所以像ES2015这样的条目会引入ECMA功能。希望计算器能够做的一件事是将输入复制到剪贴板,这是对称为window.navigator的某个对象的JavaScript操作。为了访问navigator,必须引入DOM库,这使能够与浏览器文档对象模型进行交互。可能会有点令人困惑的是,不需要DOM库来与其他标准功能(如window文档)进行交互。

交互与实现

在向表格添加计算器按钮之前,可以再做一步设置。知道表格有一个名为display的输入字段。稍后想要与之交互,所以将编写一个小程序,这将使在处理它时生活更轻松。将创建一个值,它将存储对输入的引用。由于将绑定到这个值,将添加一个帮助方法,它将在首次访问时延迟填充这个引用,并在后续调用中返回存储的版本。

let displayElement: HTMLInputElement | null = null; function getDisplay(): HTMLInputElement { if (!displayElement) { displayElement = <HTMLInputElement>document.getElementById('display'); } return displayElement; }

这段代码的意思是displayElement可以是HTMLInputElement类型,也可以是null,以指示还没有将其连接到显示元素。TypeScript非常有用,因为可以对网页输入进行强类型化,所以原本在JavaScript中是一个对象的东西可以被限制为实际类型。这很有用,因为它告诉有哪些属性和操作可用。为了填充displayElement,使用document.getElementById。这是一个标准浏览器方法,允许根据它们的id(这是在网页中的实际标签中设置的)选择元素。现在,document.getElementById的返回类型是object,所以需要使用称为类型转换的技术将其设置为适当的类型。在TypeScript中,使用<>来指定适当的类型。

<tr> <td colspan="2"> <input type="button" onclick="clearAll()" value="Clear"/> </td> <td colspan="2"> <input type="button" onclick="copyToClipboard()" value="Mem"/> </td> </tr> <tr> <td> <input type="button" value="1" onclick="display(1)"/> </td> <td> <input type="button" value="2" onclick="display(2)"/> </td> <td> <input type="button" value="3" onclick="display(3)"/> </td> <td> <input type="button" value="/" onclick="display(Operator.divide)"/> </td> </tr> <tr> <td> <input type="button" value="4" onclick="display(4)"/> </td> <td> <input type="button" value="5" onclick="display(5)"/> </td> <td> <input type="button" value="6" onclick="display(6)"/> </td> <td> <input type="button" value="-" onclick="display(Operator.subtract)"/> </td> </tr> <tr> <td> <input type="button" value="7" onclick="display(7)"/> </td> <td> <input type="button" value="8" onclick="display(8)"/> </td> <td> <input type="button" value="9" onclick="display(9)"/> </td> <td> <input type="button" value="+" onclick="display(Operator.add)"/> </td> </tr> <tr> <td> <input type="button" value="." onclick="display(Operator.period)"/> </td> <td> <input type="button" value="0" onclick="display(0)"/> </td> <td> <input type="button" value="=" onclick="solve()"/> </td> <td> <input type="button" value="*" onclick="display(Operator.multiply)"/> </td> </tr>

每个按钮都连接到四个函数中的一个,这取决于想要做什么。让从与之前添加到枚举中的数字和运算符相关的display函数开始。

function display(value: number | Operator): void { const htmlElement = getDisplay(); htmlElement.value = htmlElement.value.trim() + value; }

这个函数接受一个数字或一个运算符。喜欢TypeScript给联合运算符,它允许说值可以是这个或那个类型,使用|。在函数内部,使用上面编写的函数获取输入元素的引用。一旦有了这个元素,就从它获取值,并添加数字或运算符。调用htmlElement.value上的trim()操作,以防用户在输入的末尾放置了一个空格。

function clearAll(): void { const htmlElement = getDisplay(); htmlElement.value = ''; }

这与display函数非常相似,它获取html输入元素(事实上,将看到所有的函数都会这样做)。一旦它有了引用,它就直接与value交互,将其设置为空字符串。

function solve(): void { const htmlElement = getDisplay(); const output = eval(htmlElement.value); htmlElement.value = output; }

可能认为solve函数会很复杂,解析输入并对其进行计算。实际情况是,在标准JavaScript函数eval的帮助下,这个函数非常简单,eval函数评估输入的结果。

function copyToClipboard(): void { const htmlElement = getDisplay(); navigator.clipboard.writeText(htmlElement.value); }

可能会记得说navigator对象在window.navigator中。为了方便,代码通常不需要指定window部分,所以可以直接去navigator。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485