随手开发一个鸿蒙版仿苹果计算器
众所周知鸿蒙 JS 框架是非常轻量级的 MVVM 模式。通过使用和 Vue2 相似的属性劫持技术实现了响应式系统。

学习鸿蒙很长时间了,想写一个 demo 进行练练手,就选择开发这个仿苹果计算器程序。


话不多说,上代码
<div?class="container">
????<div?class="header">
????????<text?class="{{outputClassName}}">{{output}}</text>
????</div>
????<div?class="keyboard">
????????<block?for="{{keyArr}}">
????????????<div?if="{{$item?==?'0'}}"?class="zeroKeys"?onclick="onclickNubmer({{$item}})">
????????????????<text>
????????????????????{{$item}}
????????????????</text>
????????????</div>
????????????<div?elif="{{$item?==?'AC'?||?$item?==?'+/-'?||?$item?==?'%'}}"?class="operatorKeys-top"?onclick="onclickOper({{$item}})">
????????????????<text>
????????????????????{{$item}}
????????????????</text>
????????????</div>
????????????<div?elif="{{$item?==?'÷'?||?$item?==?'×'?||?$item?==?'-'?||?$item?==?'+'?||?$item?==?'='}}"?class="operatorKeys-right"?onclick="onclickOper({{$item}})">
????????????????<text>
????????????????????{{$item}}
????????????????</text>
????????????</div>
????????????<div?else?class="keys?keys-nubmer"?onclick="onclickNubmer({{$item}})">
????????????????<text>
????????????????????{{$item}}
????????????????</text>
????????????</div>
????????</block>
????</div>
</div>
css:
.container?{
????flex-direction:?column;
????background-color:?#010101;
????height:100%;
????width:100%;
}
.header{
????height:36%;
????width:100%;
????align-items:?flex-end;
????padding:2px?20px?2px?10px;
}
.keyboard{
????height:64%;
????width:100%;
????padding:2px?10px;
????flex-wrap:?wrap;
}
.outputText,.outputTextSmall{
????width:100%;
????height:100px;
????color:#FFFFFF;
????text-align:?end;
}
.outputText{
????font-size:80px;
}
.outputTextSmall{
????font-size:58px;
}
.keys,.zeroKeys,.operatorKeys-top,.operatorKeys-right{
????width:74px;
????height:74px;
????justify-content:?center;
????align-items:?center;
????border-radius:74px;
????margin:10px?5px;
}
.keys-nubmer,.zeroKeys{
????background-color:#333333;
}
.zeroKeys{
????width:158px;
}
.operatorKeys-top{
????background-color:?#a4a4a4;
}
.operatorKeys-right{
????background-color:?#f79f31;
}
.keys:active,.zeroKeys:active{
????background-color:?#737373;
}
.keys?text,.zeroKeys?text,.operatorKeys-right?text{
????font-size:42px;
????color:?#FFFFFF;
}
.operatorKeys-top?text{
????font-size:36px;
????color:?#010101;
}
.operatorKeys-top:active{
????background-color:?#d9d9d9;
}
.operatorKeys-right:active{
????background-color:?#f5c891;
}
js:
import?{math}?from?"../../common/js/utils.js";
export?default?{
??data:?{
????output:"0",
????outputClassName:"outputText",
????cache:[],//记录输入内容
????keyArr:["AC","+/-","%","÷","7","8","9","×","4","5","6","-","1","2","3","+","0",".","="],
????reOper:"",//记录点击的运算符
????reStr1:"",//记录第一次输入内容
????reStr2:"",//记录点击运算符后的内容
????bool:false//防止第二次输入内容时内容清空
??},
??onInit(){
????this.$watch("output","watchOutPut")
??},
??onclickOper(item){
????if(item?==?"AC"){
??????this.clearComput();
????}?else?if(item?==?"+"?||?item?==?"-"?||?item?==?"×"?||?item?==?"÷"){
??????this.reOper?=?item;
??????this.reStr1?=?this.output;
??????if(this.cache.length?>?0){
????????this.startCompute();
??????}
??????this.cache.push(this.reStr1);
????}?else?if(item?==?"+/-"){
??????this.output?=?"-"+this.output;
????}?else?if(item?==?"%"){
??????this.output?=?math.accDiv(this.output,100);
????}?else?if(item?==?"="){
??????this.reStr2?=?this.output;
??????this.cache.push(this.reStr2);
??????this.startCompute();
????}
??},
??onclickNubmer(item){
????if(this.cache.length?>?0?&&?!this.bool){
??????this.output?=?"0";
??????this.bool?=?true;
????}
????if(this.output?==?"0"?&&?item?!=?"."){
??????this.output?=?item;
????}?else?if(item?==?"."){
??????if(this.output.indexOf(".")?==?-1){
????????if(this.output?==?"0"){
??????????this.output?=?"0."
????????}?else?{
??????????this.output?+=?item;
????????}
??????}
????}?else?{
??????if(this.output.length?<?10){
????????this.output?+=?item;
??????}
????}
??},
??watchOutPut(nVal){
????if(nVal.length?>?7?&&?nVal.length<?10){
??????this.outputClassName?=?"outputTextSmall";
????}?else?{
??????this.outputClassName?=?"outputText";
????}
??},
??startCompute(){
????switch?(this.reOper)?{
??????case?"+":
????????this.output?=?math.accAdd(this.reStr1,this.reStr2);
????????this.reStr1?=?this.output;
????????break;
??????case?"-":
????????this.output?=?math.accSub(this.reStr1,this.reStr2);
????????this.reStr1?=?this.output;
????????break;
??????case?"×":
????????this.output?=?math.accMul(this.reStr1,this.reStr2);
????????this.reStr1?=?this.output;
????????break;
??????case?"÷":
????????this.output?=?math.accDiv(this.reStr1,this.reStr2);
????????this.reStr1?=?this.output;
????????break;
??????default:
????????break;
????}
??},
??clearComput(){
????this.output?=?"0";
????this.reOper?=?"";
????this.reStr1?=?"";
????this.reStr2?=?"";
????this.cache?=?[];
????this.bool?=?false;
??}
}
utils.js:
class?MathCalss?{
??//js精准除法函数
??accDiv(arg1,?arg2){
????let?t1?=?0,
???????t2?=?0,
???????r1,
???????r2;
?????try?{
???????t1?=?arg1.toString().split('.')[1].length;
?????}?catch?(e)?{}
?????try?{
???????t2?=?arg2.toString().split('.')[1].length;
?????}?catch?(e)?{}
?????r1?=?Number(arg1.toString().replace('.',?''));
?????r2?=?Number(arg2.toString().replace('.',?''));
?????return?(r1?/?r2)?*?Math.pow(10,?t2?-?t1);
??}
??//js精准加法函数
??accAdd(arg1,?arg2)?{
????var?r1,?r2,?m,?c;
????try?{
??????r1?=?arg1.toString().split(".")[1].length;
????}
????catch?(e)?{
??????r1?=?0;
????}
????try?{
??????r2?=?arg2.toString().split(".")[1].length;
????}
????catch?(e)?{
??????r2?=?0;
????}
????c?=?Math.abs(r1?-?r2);
????m?=?Math.pow(10,?Math.max(r1,?r2));
????if?(c?>?0)?{
??????var?cm?=?Math.pow(10,?c);
??????if?(r1?>?r2)?{
????????arg1?=?Number(arg1.toString().replace(".",?""));
????????arg2?=?Number(arg2.toString().replace(".",?""))?*?cm;
??????}?else?{
????????arg1?=?Number(arg1.toString().replace(".",?""))?*?cm;
????????arg2?=?Number(arg2.toString().replace(".",?""));
??????}
????}?else?{
??????arg1?=?Number(arg1.toString().replace(".",?""));
??????arg2?=?Number(arg2.toString().replace(".",?""));
????}
????return?(arg1?+?arg2)?/?m;
??}
??//js精准减法函数
??accSub(arg1,?arg2)?{
????let?r1,?r2,?m,?n;
????try?{
??????r1?=?arg1.toString().split('.')[1].length;
????}?catch?(e)?{
??????r1?=?0;
????}
????try?{
??????r2?=?arg2.toString().split('.')[1].length;
????}?catch?(e)?{
??????r2?=?0;
????}
????m?=?Math.pow(10,?Math.max(r1,?r2));
????//动态控制精度长度
????n?=?r1?>=?r2???r1?:?r2;
????return?(arg1?*?m?-?arg2?*?m)?/?m;
??}
??//js精准乘法函数
??accMul(arg1,?arg2)?{
????var?m?=?0,?s1?=?arg1.toString(),?s2?=?arg2.toString();
????try?{
??????m?+=?s1.split(".")[1].length;
????}
????catch?(e)?{
????}
????try?{
??????m?+=?s2.split(".")[1].length;
????}
????catch?(e)?{
????}
????return?Number(s1.replace(".",?""))?*?Number(s2.replace(".",?""))?/?Math.pow(10,?m);
??}
}
export?var?math?=?new?MathCalss();
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
赞助链接
排名
热点
搜索指数
- 1 习近平将发表二〇二六年新年贺词 7904141
- 2 2026年国补政策来了 7808738
- 3 东部战区:开火!开火!全部命中! 7712893
- 4 2026年这些民生政策将惠及百姓 7616985
- 5 小学食堂米线过期2.5小时被罚5万 7519709
- 6 解放军喊话驱离台军 原声曝光 7428214
- 7 为博流量直播踩烈士陵墓?绝不姑息 7327605
- 8 每月最高800元!多地发放养老消费券 7238391
- 9 数字人民币升级 1月1日起将计付利息 7141831
- 10 2026年1月1日起 一批新规将施行 7040675





![Dull-迷人都去给我加真爱粉群,我以后要狂发真爱粉了[怒骂] ](https://imgs.knowsafe.com:8087/img/aideep/2024/1/15/f4cfcb00307ed9da34c1ff6ff048b17c.jpg?w=250)


51CTO技术栈
