赞
踩
在日常生活中,计算器是人们广泛使用的工具,可以帮助我们快速且方便地计算金额、成本、利润等。下面将会讲解如何开发一个“计算器”微信小程序。
“计算器”微信小程序的页面效果如图所示
在计算器中可以进行整数和小数的加(+)、减(-)、乘(×)、除(÷)运算。“C”按钮为清除按钮,表示将输入的数字全部清空;“DEL”按钮为删除按钮,表示删除前面输入的一个数字;“+/-”按钮为正负号切换按钮,用于实现正负数切换;“.”按钮为小数点按钮,表示在计算过程中可以输入小数进行计算;“=”按钮为等号按钮,表示对输入的数字进行计算。
此计算器本本质是对数学表达式的求解,例如 Z=X+Y,其中,X,Y为两个自变量,Z为因变量,主要设计思路为千先输入X,Y,和"+"号,再输入“=”号计算结果并显示 。由此可知,基本操作为:
(1)输入第一个数字(存储为变量num1并显示)。
(2)输入运算符(存储为num2并显示)。
(3)输入运算符(形成表达式并显示)。
(4)按下”=“(计算结果并显 示)。
根据以上分析可知,处理逻辑主要编写以下三个函数
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; }
data-*是微信小程序的自定义属性,由data-前缀加上自定义的属性名,自定义属性值表示要传递的数据 ,在事件处理函数中通过targert或currentTarget对象的datasett属性获取数据
微信小程序提供了模块化开发的语法,,使用module.exports语法对外暴露接口,然后在需要使用模块的地方通过require()函数引入 模块。
模块代码如下:
-
- // 精确计算
- 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分别为加、减、乘、除函数。
- // 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进行双向绑定的数据显示。
其它的事件处理函数如代码所示,分别完成复位、小数点、删除等处理函数,处理逻辑请参照代码。
本文主要论述了微信小程序计算器的设置,从思路、界面、计算模块、处理逻辑等方面进行了详细的论述,并给出了源代码。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。