在日常生活中,计算器是人们广泛使用的工具,可以帮助我们快速且方便地计算金额、成本、利润等。下面将会讲解如何开发一个“计算器”微信小程序。
一、开发思路
1、界面和功能
“计算器”微信小程序的页面效果如图所示
在计算器中可以进行整数和小数的加(+)、减(-)、乘(×)、除(÷)运算。“C”按钮为清除按钮,表示将输入的数字全部清空;“DEL”按钮为删除按钮,表示删除前面输入的一个数字;“+/-”按钮为正负号切换按钮,用于实现正负数切换;“.”按钮为小数点按钮,表示在计算过程中可以输入小数进行计算;“=”按钮为等号按钮,表示对输入的数字进行计算。
2、计算器设计数学原理
此计算器本本质是对数学表达式的求解,例如 Z=X+Y,其中,X,Y为两个自变量,Z为因变量,主要设计思路为千先输入X,Y,和"+"号,再输入“=”号计算结果并显示 。由此可知,基本操作为:
(1)输入第一个数字(存储为变量num1并显示)。
(2)输入运算符(存储为num2并显示)。
(3)输入运算符(形成表达式并显示)。
(4)按下”=“(计算结果并显 示)。
3. 设计主要思路
根据以上分析可知,处理逻辑主要编写以下三个函数
numBtn():处理函数三个数字按钮的事件处理函数
opBtn:运算符按钮的事件处理函数
execBtn():编写“=”按钮的事件处理函数
设计三个标识用以标识用户的三种状态,其中,数字改变标识为真:
numChangeFlag
: 数字改变标识,第一数字和第二数字切换标识,初始值为false
execflag: 执行状态标识,初始值为false
resultflag: 结果状态标识,初始值为false
具体的处理逻辑详见四处理逻辑
二、界面设计
据以上的开发思路,界面分为显示区和按钮区,其中显示区又分为数字显示区、公式显示区两部分,上下排列;按钮可分为数字按钮,运算符按钮,功能按钮三部分,按钮显示区按四行四列显示,其中“0”独占两个单元格。代码如下所示:
<!--index.wxml-->
<navigation-bar title="计算器" back="{{false}}" color="black" background="#FFF"></navigation-bar>
<!--结果区域-->
<view class="result">
<view class="result-num">{{num}}</view>
<view class="result-sub">{{sub}}</view>
</view>
<!--按钮区域-->
<view class="btns">
<view>
<view hover-class="bg" hover-stay-time="50" bindtap="resetBtn">C</view>
<view hover-class="bg" hover-stay-time="50" bindtap="delBtn">DEL</view>
<view hover-class="bg" hover-stay-time="50" bindtap="negBtn">+/-</view>
<view hover-class="bg" hover-stay-time="50" bindtap="opBtn" data-val='×'>×</view>
</view>
<view>
<view hover-class="bg" bindtap="numBtn" data-val="7">7</view>
<view hover-class="bg" bindtap="numBtn" data-val="8">8</view>
<view hover-class="bg" bindtap="numBtn" data-val="9">9</view>
<view hover-class="bg" bindtap="opBtn" data-val="÷">÷</view>
</view>
<view>
<view hover-class="bg" bindtap="numBtn" data-val="4">4</view>
<view hover-class="bg" bindtap="numBtn" data-val="5">5</view>
<view hover-class="bg" bindtap="numBtn" data-val="6">6</view>
<view hover-class="bg" bindtap="opBtn" data-val="-">-</view>
</view>
<view>
<view hover-class="bg" bindtap="numBtn" data-val="1">1</view>
<view hover-class="bg" bindtap="numBtn" data-val="2">2</view>
<view hover-class="bg" bindtap="numBtn" data-val="3">3</view>
<view hover-class="bg" bindtap="opBtn" data-val="+">+</view>
</view>
<view>
<view hover-class="bg" bindtap="numBtn" data-val="0">0</view>
<view hover-class="bg" bindtap="dotBtn">.</view>
<view hover-class="bg" bindtap="execBtn" data-val="=">=</view>
</view>
</view>
界面布置总体上采用“flex”流式布局column方式,上下排列,按钮区以每四个按钮为一组,共分四组,同样采用flex的流式布局,具体css代码如下所示:
/**index.wxss**/
page {
display: flex;
flex-direction: column;
height: 100vh;
color: #555;
}
.result {
flex: 1;
background: #f3fef6;
position: relative;
}
.result-num {
position: absolute;
font-size: 15vw;
bottom: 5vh;
right: 3vw;
}
.result-sub{
font-size: 10vw;
position: absolute;
bottom: 1vh;
right: 3vw;
}
.btns {
flex: 1;
}
/* 按钮样式 */
.bg {
background: #eee;
}
.btns {
flex: 1;
display: flex;
flex-direction: column;
font-size: 64rpx;
border-top: 1rpx solid #ccc;
border-left: 1rpx solid #ccc;
}
.btns > view {
flex: 1;
display: flex;
}
.btns > view > view {
flex-basis: 25%;
border-right: 1rpx solid #ccc;
border-bottom: 1rpx solid #ccc;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.btns > view:last-child > view:first-child {
flex-basis: 50%;
}
.btns > view:first-child > view:first-child {
color: #f00;
}
.btns > view > view:last-child {
color: #fc8e00;
}
三,知识储备
1、data-*自定义属性
data-*是微信小程序的自定义属性,由data-前缀加上自定义的属性名,自定义属性值表示要传递的数据 ,在事件处理函数中通过targert或currentTarget对象的datasett属性获取数据
2、模块
微信小程序提供了模块化开发的语法,,使用module.exports语法对外暴露接口,然后在需要使用模块的地方通过require()函数引入 模块。
四、处理逻辑
1、数学处理模块
模块代码如下:
// 精确计算
module.exports = {
target: 'num1', //表示当前正在输入哪个数字,取num1或num2
num1: '0',
num2: '0',
op: '',
// 重置
reset() {
this.num1 = '0'
this.num2 = '0'
this.target = 'num1'
this.op = ''
},
changeNum2: function()
{
this.target='num2'
},
setNum: function(arg1){
this[this.target]=arg1
},
getNum: function(){
return this[this.target]
},
add: function(arg1, arg2) {
var r1, r2, m
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))
return (arg1 * m + arg2 * m) / m
},
sub: function(arg1, arg2) {
var 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).toFixed(n)
},
mul: function(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)
},
div: function(arg1, arg2) {
var 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)
},
// 进行运算
getResult() {
let result = 0
if (this.op === '+') {
result = this.add(this.num1, this.num2)
} else if (this.op === '-') {
result = this.sub(this.num1, this.num2)
} else if (this.op === '×') {
result = this.mul(this.num1, this.num2)
} else if (this.op === '÷') {
result =this. div(this.num1, this.num2)
}
return result
}
}
模块全局变量:
target: 'num1', //表示当前正在输入哪个数字,取num1或num2
num1: '0', //第一个操作数
num2: '0', //第二个操作数
op: '', //操作符
模块函数:
changeNum2(): //设置当前操作数为第二操作数
setNum(): //设置操作数的值
getNum(): //获取操作数的值
getResult(): //获取计算结果
其它的 add,sub,mul,div分别为加、减、乘、除函数。
2、计算器处理逻辑
// index.js
const calc = require('../../utils/calc.js')
Page({
/** 页面的初始数据 */
data: {
num: '0',
op:''
},
//设置变量标识
numChangeFlag : false,
execflag: false,
resultflag: false,
//数字按钮的事件处理函数
numBtn: function(e) {
//点击数字按钮,获取对应的数字,将其值赋给num
var num=e.target.dataset.val
if(this.resultflag){
this.resetBtn()
}
if(this.numChangeFlag){
this.numChangeFlag=false
this.execflag=true
this.data.num='0'
calc.changeNum2()
}
//设置输入的数字
calc.setNum(this.data.num=='0'? num : this.data.num +num)
//页面中显示数字
this.setData({ num: calc.getNum() })
},
//运算符按钮处理函数
opBtn: function(e){
calc.op=e.target.dataset.val
this.numChangeFlag=true
//判断是否已输入第2个数字
if(this.execflag){
this.execflag=false
//已经输入第2个数字,再判断是否有结果状态
if(this.resultflag){
this.resultflag=false
} else {
calc.num1=calc.getResult()
}
}
this.setData({
sub: calc.num1+' '+calc.op+' ',
num: calc.num1
})
},
//"="按钮事件处理函数
execBtn: function(){
//解决没有输入第2个数字,不能按=号问题
if(this.numChangeFlag){
this.numChangeFlag=false
this.execflag=true
calc.num2=this.data.num
}
//如果已经输入第2个数字,执行计算操作
if(this.execflag){
this.resultflag=true
var result=calc.getResult()
this.setData({
sub: calc.num1+' '+calc.op+' '+calc.num2+'=',
num: result
})
calc.num1=result
}
} ,
//重置按钮事件处理函数
resetBtn:function(){
calc.reset()
this.execflag=false
this.numChangeFlag=false
this.resultflag=false
this.setData({
sub: '',
num: '0'
})
},
//小数点按钮事件
dotBtn:function(){
//如果是计算结果状态,则重置计算器
if(this.resultflag){
this.resetBtn()
}
//如果等待输入第2个数字且还没有输入第2个数字,设为‘0’
if(this.numChangeFlag) {
this.numChangeFlag=false
calc.setNum('0.')
} else if(this.data.num.indexOf('.')<0){
//如果当前数字没有".",需要加上"."
calc.setNum(this.data.num+'.')
}
this.setData({
num: calc.getNum(),
})
},
//删除按钮事件处理函数
delBtn:function(){
//如果当前是计算结果状态,则重置计算器
if(this.resultflag) {
return this.resetBtn()
}
//非计算结果状态
var num=this.data.num.substr(0,this.data.num.length-1)
calc.setNum(num==='' || num==='-' || num==='-0.' ? '0' : num)
this.setData({
num: calc.getNum()
})
},
//正负切换按钮事件处理函数
negBtn:function(){
//如果是0,不加正负号
if(this.data.num==='0' || this.data.num==='0.'){
return
}
//如果当前是计算结果状态,则重置计算器
if(this.resultflag){
this.resetBtn()
} else if(this.data.num.indexOf('-')<0){
//当前没有负号,加负号
calc.setNum('-'+this.data.num)
} else {
//当前有负号,去掉负号
calc.setNum(this.data.num.substr(1))
}
this.setData({
num: calc.getNum()
})
},
})
模块首先使用require()函数引入计算模块,其次是全局变量、事件处理函数,具体事件处理函数如下:
numBtn:数字键处理函数,具体逻辑如下:首先判断是否是结果状态,如果是结果状态则复位,否则判断是第二操作数状态,是则设置为第二操作数。最后,使用计算模块的setNum设置操作数,并使用setData进行双向绑定的数据显示。
execBtn:"="事件处理函数,此函数的主要作用是调用计算模块的getResult函数,获取计算结果,并使用setData进行双向绑定的数据显示。
其它的事件处理函数如代码所示,分别完成复位、小数点、删除等处理函数,处理逻辑请参照代码。
本文主要论述了微信小程序计算器的设置,从思路、界面、计算模块、处理逻辑等方面进行了详细的论述,并给出了源代码。