React+TypeScript+Vite语音识别计算器npm run dev后空白页求助
带语音识别功能的计算器空白页问题修复与完整实现
核心问题分析
启动后页面空白及功能失效的原因包括:
- main.tsx未实现React应用的DOM挂载逻辑,组件无法渲染到页面
- 语音识别模块未读取转录结果,语音输入无法转化为计算表达式
- calculate函数硬编码固定值,未使用用户输入内容进行计算
分步修复方案
1. 完善main.tsx的渲染入口
添加React应用挂载代码,将App组件渲染到页面根节点(需确保项目HTML文件中存在id为root的节点)。
2. 修复Calculator组件的语音识别与计算逻辑
- 获取语音识别的
transcript字段,将语音内容转换为可计算的表达式 - 修正calculate函数,使用用户输入的表达式进行计算
- 处理语音转录中的自然语言运算符(如将"plus"转为"+"、"minus"转为"-"等)
3. 确保样式路径正确
确认组件中样式文件的导入路径与实际文件结构匹配,避免样式加载失败导致组件不可见
完整代码实现
main.tsx
import React from "react"; import ReactDOM from "react-dom/client"; import Calculator from "./Component/Calculator"; import "./styles/calculator.css"; function App() { return ( <div className="App"> <Calculator /> </div> ); } ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <App /> </React.StrictMode> );
Calculator.tsx
import React, { useState } from "react"; import SpeechRecognition, { useSpeechRecognition } from "react-speech-recognition"; import "../styles/calculator.css"; function Calculator() { const [result, setResult] = useState(""); const { transcript, resetTranscript } = useSpeechRecognition(); // 将语音转录的自然语言转换为计算运算符 const convertVoiceToExpression = (text: string): string => { return text .replace(/plus/gi, "+") .replace(/minus/gi, "-") .replace(/multiply by/gi, "*") .replace(/divided by/gi, "/") .replace(/equals/gi, "=") .replace(/\s+/g, ""); }; const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => { setResult(result.concat(e.currentTarget.name)); }; const clear = () => { setResult(""); }; const backspace = () => { setResult(result.slice(0, -1)); }; function evaluateExpression(expression: string): string { try { // 过滤非法字符,仅保留数字、运算符和小数点 const sanitizedExpr = expression.replace(/[^0-9+\-*/.]/g, ""); if (!sanitizedExpr) return ""; // eslint-disable-next-line no-new-func const calcResult = Function(`"use strict"; return (${sanitizedExpr})`)(); return calcResult.toString(); } catch (error) { console.error(error); return "Error"; } } const calculate = (inputExpr?: string) => { try { const expression = inputExpr || result; const calcResult = evaluateExpression(expression); setResult(calcResult); } catch (error) { console.error(error); setResult("Error"); } }; const handleVoiceRecognition = () => { if (!SpeechRecognition.browserSupportsSpeechRecognition()) { alert("你的浏览器不支持语音识别功能"); return; } resetTranscript(); SpeechRecognition.startListening({ continuous: true, language: "zh-CN", // 可根据需求切换为"en-US" }); }; const stopVoiceRecognition = () => { SpeechRecognition.stopListening(); const voiceExpr = convertVoiceToExpression(transcript); setResult(voiceExpr); calculate(voiceExpr); }; return ( <div className="calculator"> <input type="text" value={result} readOnly /> <div className="keypad"> <button className="operator" onClick={clear}>AC</button> <button className="operator" onClick={backspace}>C</button> <button className="operator" name="+" onClick={handleClick}>+</button> <button name="7" onClick={handleClick}>7</button> <button name="8" onClick={handleClick}>8</button> <button name="9" onClick={handleClick}>9</button> <button className="operator" name="-" onClick={handleClick}>-</button> <button name="4" onClick={handleClick}>4</button> <button name="5" onClick={handleClick}>5</button> <button name="6" onClick={handleClick}>6</button> <button className="operator" name="*" onClick={handleClick}>x</button> <button name="1" onClick={handleClick}>1</button> <button name="2" onClick={handleClick}>2</button> <button name="3" onClick={handleClick}>3</button> <button className="operator" name="/" onClick={handleClick}>÷</button> <button name="." onClick={handleClick}>.</button> <button name="0" onClick={handleClick}>0</button> <button className="operator" onClick={() => calculate()}>=</button> <button className="operator" onClick={handleVoiceRecognition}>🎤</button> <button className="operator" onClick={stopVoiceRecognition}>🛑</button> </div> </div> ); } export default Calculator;
calculator.css
.calculator { display: flex; flex-direction: column; align-items: center; justify-content: center; margin: 20px auto; max-width: 300px; background-color: #f9f9f9; border-radius: 10px; padding: 20px; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); } .calculator input[type="text"] { display: block; width: 100%; margin-bottom: 10px; padding: 10px; font-size: 24px; text-align: right; border: none; border-radius: 5px; box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); } .keypad { display: grid; grid-template-columns: repeat(4, 1fr); grid-gap: 10px; } button { background-color: #e0e0e0; color: #333; font-size: 20px; padding: 10px; border: none; border-radius: 5px; cursor: pointer; transition: all 0.2s ease-in-out; } button:hover { background-color: #333; color: #fff; } .operator { background-color: #ff8c00; color: #fff; } .operator:hover { background-color: #f60; }
内容的提问来源于stack exchange,提问作者Kevin Paul Babu
相关产品推荐
相关产品推荐

