React + Vite 手写仿桌面窗口加减法计算器:拖动、最小化、键盘输入、历史记录
2026/8/7 7:00:10 网站建设 项目流程

React + Vite 手写仿桌面窗口加减法计算器:拖动、最小化、键盘输入、历史记录

项目简介

这是一个基于 Vite + React 的加减法计算器,重点不是“会算加减法”,而是把浏览器页面做成一个完整的“桌面窗口”体验:

  • 计算器可以自由拖动。
  • 标题栏有最小化和关闭按钮。
  • 关闭后可以在底部任务栏重新打开。
  • 支持鼠标点击和键盘输入。
  • 保留最近 12 条历史记录。

核心状态设计

计算器不是一堆分散的useState,而是围绕一次计算过程设计的:

input -> 当前显示的数字字符串 operand1 -> 第一个操作数 operator -> add / subtract justEvaluated-> 刚按下等于,再次输入数字时是否覆盖显示

关键交互:

  1. 输入数字时,最多 14 位。
  2. 按下运算符时,如果上一组操作还没结算,先自动结算再继续。
  3. =时把表达式写进历史记录,并把结果作为下一次计算的起点。
  4. 所有结果用toFixed(10)后再转回浮点数,避免0.1 + 0.2这类浮点误差直接展示。

核心计算逻辑:

function compute(a, b, operator) { return operator === 'add' ? a + b : a - b } function pressOperator(nextOperator) { const current = parseInput(input) if (operand1 !== null && operator !== null) { const result = roundResult(compute(operand1, current, operator)) setOperand1(result) setInput(formatNumber(result)) } else { setOperand1(current) } setOperator(nextOperator) setInput('0') setJustEvaluated(false) } function evaluate() { if (operand1 === null || operator === null) return const second = parseInput(input) const result = roundResult(compute(operand1, second, operator)) const expression = `${formatNumber(operand1)} ${operatorSymbol(operator)} ${formatNumber(second)}` setHistory((current) => [{ id: Date.now(), expression, result: formatNumber(result) }, ...current].slice(0, 12), ) setInput(formatNumber(result)) setOperand1(result) setOperator(null) setJustEvaluated(true) }

窗口拖动怎么实现

窗口拖动使用 Pointer Events:

  1. 在标题栏按下时记录鼠标相对窗口左上角的偏移。
  2. 移动时根据鼠标位置计算新坐标。
  3. clamp把窗口限制在屏幕范围内,不允许拖出桌面。
  4. 每次操作提升zIndex,让当前窗口保持最前。
function startDrag(event) { if (event.target.closest('.titlebar__controls')) return bringToFront() const rect = windowRef.current.getBoundingClientRect() dragOffset.current = { x: event.clientX - rect.left, y: event.clientY - rect.top, } isDragging.current = true event.currentTarget.setPointerCapture(event.pointerId) } function moveDrag(event) { if (!isDragging.current || !windowRef.current) return const rect = windowRef.current.getBoundingClientRect() const maxX = Math.max(8, window.innerWidth - rect.width - 8) const maxY = Math.max(8, window.innerHeight - rect.height - 56) setWindowPos({ x: clamp(event.clientX - dragOffset.current.x, 8, maxX), y: clamp(event.clientY - dragOffset.current.y, 8, maxY), }) }

键盘支持

页面挂在window上的keydown监听器,让计算器不需要鼠标也能完整使用:

  • 0-9:输入数字
  • .:小数点
  • +/-:选择运算
  • Enter/=:计算
  • Backspace:退格
  • Escape/Delete/C:全部清空

界面布局

界面主要由三部分组成:

  1. 标题栏:应用名、最小化、关闭。
  2. 显示区:上一行显示表达式,下一行显示当前值。
  3. 按键区:数字、加减、退格、清空、等于。

底部还有一个任务栏,显示计算器按钮和当前时间,让“关闭窗口再重新打开”的交互更像真实桌面。

运行方式

npminstallnpmrun dev

生产构建:

npmrun build

可扩展方向

  • 增加乘除和括号,扩展成完整四则运算。
  • 增加百分比、正负号、平方根等科学计算按键。
  • 历史记录增加一键回填,点击某条历史结果继续计算。
  • 增加深色主题和不同桌面壁纸。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询