用 JavaScript 和 HTML 制作一个计算器

用 JavaScript 和 HTML 制作一个计算器

 

引言

这是一篇很棒的文章,在这里你可以学习如何从零做出一款计算器。我们希望你使用 JavaScript 开发并且思考怎么构建一款计算器, 如何编写代码,以及最后,如何整理自己的代码。

在这篇文章结束,你会得到一款和 iPhone 计算器功能一样的计算器(除了 +/- 和百分比功能外)。

前置条件

在你开始本节课程前,请确保你对 JavaScript 有一个不错的了解。最起码,你需要知道以下事情:

  1. If/else 分支
  2. For 循环
  3. JavaScript 函数
  4. 箭头函数
  5. && 和 || 操作符
  6. 如何使用textContent属性修改文本
  7. 如何使用事件代理模式添加事件

开始之前

我建议你在开始课程之前自己尝试下自己开发计算器。这是一个很好的锻炼,因为你会训练自己像开发人员一样思考。
一旦你尝试了一小时,再回来上这节课(不管你是成功还是失败。当年尝试过,思考过,这会帮助你在更短的时间内吸收本节课的内容)。

就这样,我们先来了解下计算器的工作原理。如果对Python有兴趣,想了解更多的Python以及AIoT知识,解决测试问题,以及入门指导,帮你解决学习Python中遇到的困惑,我们这里有技术高手。如果你正在找工作或者刚刚学校出来,又或者已经工作但是经常觉得难点很多,觉得自己Python方面学的不够精想要继续学习的,想转行怕学不会的, 都可以加入我们,可领取最新Python大厂面试资料和Python爬虫、人工智能、学习资料!VX【pydby01】暗号CSDN

构建计算器

首先,我们想要建立计算器。

这个计算机包含两个部分:显示屏和键盘。

<div class=”calculator”>
  <div class=”calculator__display”>0</div>
  <div class=”calculator__keys”> … </div>
</div>

我们使用 CSS Grid 去制作键盘部分,因为他们是类似网格的格式进行排列的。这里已经在启动文件中完成了,你可以在以下地址找到启动文件 此处.

.calculator__keys { 
  display: grid; 
  /* other necessary CSS */ 
}

为了帮助我们区分操作符,小数点,清除符号以及等号,我们将设置一个data-action属性用来描述他们的功能。

<div class="calculator__keys">
  <button class="key--operator" data-action="add">+</button>
  <button class="key--operator" data-action="subtract">-</button
  <button class="key--operator" data-action="multiply">&times;</button>
  <button class="key--operator" data-action="divide">÷</button
  <button>7</button>
  <button>8</button>
  <button>9</button>
  <button>4</button>
  <button>5</button>
  <button>6</button>
  <button>1</button>
  <button>2</button>
  <button>3</button>
  <button>0</button>
  <button data-action="decimal">.</button>
  <button data-action="clear">AC</button>
  <button class="key--equal" data-action="calculate">=</button>
</div>

监听键盘点击

当一个人拿着几个计算器,他会做五种事情,他们可以点击:

  1. 一个数字键(0-9)
  2. 一个操作键 (+,-,×,÷)
  3. 小数点键
  4. 等号键
  5. 清除键

构建这个计算器的第一步是能够监听所有(1)的按键,确定(2)被按下时候的类型。在这个案例中,我们可以使用事件代理模式去监听,因为所有的按键都是.calculator__keys的孩子。

const calculator = document.querySelector(‘.calculator’)
const keys = calculator.querySelector(‘.calculator__keys’)

keys.addEventListener(‘click’, e => {
 if (e.target.matches(‘button’)) {
   // Do something
 }
})


接下来,我们利用data-action属性去确定点击按键的类型。

const key = e.target
const action = key.dataset.action

如果按键没有data-action属性,那么它一定是一个数字键。

if (!action) {
  console.log('number key!')
}

如果这个按键有data-action,它的值是 addsubtractmultiply或者divide,我们就可以知道这是一个操作按键。

if (
  action === 'add' ||
  action === 'subtract' ||
  action === 'multiply' ||
  action === 'divide'
) {
  console.log('operator key!')
}

如果这个按键的data-action属性是decimal,我们就可以知道使用者点击了小数点键。

按照同样的思路,如果键的data-actionclear,我们知道用户点击了清除(写着 AC 的那个)键。如果键的data-actioncalculate,我们知道用户点击了等于键。

if (action === 'decimal') {
  console.log('decimal key!')
}

if (action === 'clear') {
  console.log('clear key!')
}

if (action === 'calculate') {
  console.log('equal key!')
}

在这里,你可以使用console.log方法,来响应每个按键的事件。

开始构建 happy path

让我们思考一下,一个普通人拿到一个计算器之后,会做什么呢?这个普通人会做什么的问题被称作 happy path

这个普通人我们就称作 Mary 吧。
当 Mary拿起计算器时,她可能会点击任何一个按键:

  1. 一个数字键(0-9)
  2. 一个操作键 (+,-,×,÷)
  3. 小数点键
  4. 等号键
  5. 清除键

一下子要思考五种按键可以能不太容易,所以让我们一步一步来。

当使用者按下数字键

如果计算器显示 0(默认数字),此时,目标数字需要替换这个 0。

如果计算器显示的是非零数字,那么目标数字就需要在显示的数字后面添加上。

现在,我们需要知道两件事情:

  1. 当前被点击的按键的数字。
  2. 当前显示的数字。

我们可以通过textContent和点击按键的.calculator__display分别获取到这两个值。

const display = document.querySelector('.calculator__display')

keys.addEventListener('click', e => {
  if (e.target.matches('button')) {
    const key = e.target
    const action = key.dataset.action
    const keyContent = key.textContent
    const displayedNum = display.textContent
    // ...
  }
})

如果计算器显示0,我们需要用点击按键的数字替换计算器显示屏的数字。 我们可以通过显示屏的textContent属性进行替换。

if (!action) {
  if (displayedNum === '0') {
    display.textContent = keyContent
  }
}

如果计算器显示的是非零数字,我们需要在当前显示的数字后面追加点击键的数字。 要追加一个数字,我们就需要一个连接字符串。

if (!action) {
  if (displayedNum === '0') {
    display.textContent = keyContent
  } else {
    display.textContent = displayedNum + keyContent
  }
}

这时,Mary 可能会点击其中一个按键:

  1. 小数点键
  2. 操作符键

让我们告诉 Mary 点击一下小数点键吧。

当使用者点击小数点键时

当 Mary 点击了小数点键之后,小数点就需要出现在显示屏上。如果 Mary 在敲击小数键后敲击任何数字,那么数字也应该添加在显示屏上。

为了实现上述效果,我们需要将.添加到已经显示的数字后面。如果对Python有兴趣,想了解更多的Python以及AIoT知识,解决测试问题,以及入门指导,帮你解决学习Python中遇到的困惑,我们这里有技术高手。如果你正在找工作或者刚刚学校出来,又或者已经工作但是经常觉得难点很多,觉得自己Python方面学的不够精想要继续学习的,想转行怕学不会的, 都可以加入我们,可领取最新Python大厂面试资料和Python爬虫、人工智能、学习资料!VX【pydby01】暗号CSDN

if (action === 'decimal') {
  display.textContent = displayedNum + '.'
}

接下来,我们可以让 Mary 继续点击计算器的操作按键继续她的计算。

当使用者点击操作按钮

如果 Mary 点击操作按键,这个操作符需要被高亮,这样的话 Mary 就知道了这个操作符是激活的。

为了实现这个功能,我们给操作符按钮添加一个名字叫is-depressed的类名。

if (
  action === 'add' ||
  action === 'subtract' ||
  action === 'multiply' ||
  action === 'divide'
) {
  key.classList.add('is-depressed')
}

一旦 Mary 按下了一个操作键,她将会点击另外的数字键。

当使用者在点击了操作键后点击了数字键

当 Mary 再次点击了数字键,之前显示的数字应该被替换成新的数组。操作键也应该被解除“被点击”的状态。

我们可以使用forEach循环遍历所有的按键,去移除is-depressed类:

keys.addEventListener('click', e => {
  if (e.target.matches('button')) {
    const key = e.target
    // ...
    
    // Remove .is-depressed class from all keys
    Array.from(key.parentNode.children)
      .forEach(k => k.classList.remove('is-depressed'))
  }
})

接下来,我们想要把显示的内容更新为之前点击过的按键。在我们做这件事之前,我们需要判断之前的按键是否是一个操作键。

我们可以通过自定义属性来实现。让我们定义一个自定义属性data-previous-key-type

const calculator = document.querySelector('.calculator')
// ...

keys.addEventListener('click', e => {
  if (e.target.matches('button')) {
    // ...
    
    if (
      action === 'add' ||
      action === 'subtract' ||
      action === 'multiply' ||
      action === 'divide'
    ) {
      key.classList.add('is-depressed')
      // Add custom attribute
      calculator.dataset.previousKeyType = 'operator'
    }
  }
})

If the previousKeyType is an operator, we want to replace the displayed number with clicked number.
如果previousKeyType是一个操作符,我们希望可以用当前点击的数字替换当前显示的数字。

const previousKeyType = calculator.dataset.previousKeyType

if (!action) {
  if (displayedNum === '0' || previousKeyType === 'operator') {
    display.textContent = keyContent
  } else {
    display.textContent = displayedNum + keyContent
  }
}

接下来让我们告诉 Mary 点击等号键来完成她的计算。

当使用者点击等号键时

当 Mary 点击等号键,计算器应该根据三个值计算一个结果:

  1. 第一个输入计算器中的数字
  2. 操作符
  3. 第二个输入计算器中的数字

在计算之后,结果会替换当前已显示的值出现在屏幕上。

这里我们只知道第二个数字是当前已经显示的数字。

if (action === 'calculate') {
  const secondValue = displayedNum
  // ...
}

为了获取第一个数字,我们需要储存之前在计算器上被我们已经清除了的值。我们可以添加一个自定义的属性,在我们点击操作键是储存第一个值。

获取操作符,我们可以使用同样的方法。

if (
  action === 'add' ||
  action === 'subtract' ||
  action === 'multiply' ||
  action === 'divide'
) {
  // ...
  calculator.dataset.firstValue = displayedNum
  calculator.dataset.operator &#
  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值