一、运行效果
- 录屏演示多次计算
二、知识储备
(一)data-*自定义属性
(二)模块
三、实现步骤
(一)准备工作
1、创建项目
- 创建微信小程序项目 -
计算器
- 单击【确定】按钮
- 按照惯例,做一些初始化工作
2、设置导航栏
- 在
app.json
设置window
配置项
(二)实现页面结构
-
pages/index/index.wxml
文件
1、编写页面整体结构
2、编写结果区域结构
- 两行内容:第一行是当前的计算式,第二行是当前计算结果
3、编写按钮区域第一行按钮的结构
- 第一行包含四个按钮:清楚按钮、删除按钮、正负号切换按钮、除号按钮
- 第20行代码设置了
data-val
自定义属性,用于区分不同按钮
4、编写按钮区域第二行按钮的结构
- 第二行包含四个按钮:7按钮、8按钮、9按钮、乘号按钮
- 四个按钮都设置了
data-val
自定义属性,用于区分不同按钮
5、编写按钮区域第三行按钮的结构
- 第三行包含四个按钮:4按钮、5按钮、6按钮、减号按钮
- 四个按钮都设置了
data-val
自定义属性,用于区分不同按钮
6、编写按钮区域第四行按钮的结构
- 第四行包含四个按钮:1按钮、2按钮、3按钮、加号按钮
- 四个按钮都设置了
data-val
自定义属性,用于区分不同按钮
7、编写按钮区域第五行按钮的结构
- 第五行包含四个按钮:0按钮、点按钮、3按钮、加号按钮
- 第68行设置了
data-val
自定义属性,用于区分不同按钮 - 查看预览效果
(三)实现页面样式
-
pages/index/index/wxss
文件
1、编写页面样式
- 设置
page
样式
2、编写结果区域样式
- 结果区域有三个样式类:
result
、result-sub
和result-sum
- 修改页面结构,暂时查看预览效果
- 查看预览效果之后,将页面结构改回去
3、编写按钮区域样式
(1)按钮区域总体样式
-
.btns
样式类
- 查看预览效果
(2)按钮区域中每一行的样式
-
.btns > view
样式类
- 查看预览效果
(4)按钮区域每一行中每个按钮的样式
-
.btns > view > view
样式类
- 查看预览效果
(5)让0按钮垮2列
-
.btns > view:first-child > view:first-child
选择器
- 查看预览效果
(6)清除按钮样式
-
.btns > view:first-child > view:first-child
选择器
- 查看预览效果
(7)最后一列按钮样式
-
.btns > view > view:last-child
选择器
- 查看预览效果
(8)按钮的盘旋样式类
-
.bg
选择器
- 查看预览效果
4、页面样式源码
/**index.wxss**/
page {
height: 100vh;
display: flex;
flex-direction: column;
color: #555;
}
/* 结果区域样式 */
.result {
flex: 1; /*平均分布手机屏幕,因为flex-direction: column*/
background: #f3f3f3;
position: relative;
}
/* 当前计算式样式 */
.result-sub {
font-size: 52rpx;
position: absolute;
bottom: 16vh;
right: 3vw;
}
/* 当前计算结果样式 */
.result-num {
font-size: 100rpx;
position: absolute;
bottom: 3vh;
right: 3vw;
}
/* 按钮区域样式 */
.btns {
display: flex;
flex: 1;
flex-direction: column;
font-size: 38rpx;
border-top: 1rpx solid #ccc;
border-left: 1rpx solid #ccc;
}
/* 按钮区域中每一行的样式 */
.btns>view {
display: flex;
flex: 1;
}
/* 按钮区域每一行中每个按钮的样式 */
.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; /* 主轴居中 - 水平居中 */
}
/* 0按钮跨2列, .btns view:last-child view:nth-child(1) */
.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: orange;
}
/* 按钮的盘旋样式类 */
.bg {
background: #eee;
}
(四)创建工具模块
- 在项目根目录创建
utils
目录
1、数字模块 - math.js
- 在
utils
目录里创建math.js
文件
// 精准计算功能,用于解决JavaScript浮点数运算精度不准确的问题
module.exports = {
// 加法
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)
}
}
- 演示处理方式
2、计算模块 - calc.js
- 在
utils
目录里创建calc.js
文件
// 引入math.js模块,获取math对象
const math = require('./math')
// 计算器中的数字处理
module.exports = {
target : 'num1', //表示当前正在输入的哪个数字,取num1或num2
num1 : '0', //保存第一个数字
num2 : '', //保存第二个数字
op : '', //运算符,值可以是+、-、×、÷
//设置当前数字
setNum(num) {
this[this.target] = num
},
// 获取当前数字
getNum() {
return this[this.target]
},
// 切换到第二个数字
changeNum2() {
this.target = 'num2'
},
//重置
reset() {
this.num1 = '0'
this.num2 = '0'
this.target = 'num1'
this.op = ''
},
// 进行计算
getResult() {
let result = 0
if (this.op === '+') {
result = math.add(this.num1,this.num2)
} else if (this.op === '-') {
result = math.sub(this.num1,this.num2)
} else if (this.op === '×'){
result = math.mul(this.num1,this.num2)
} else if (this.op === '÷') {
result = math.div(this.num1,this.num2)
}
return result
}
}
(五)实现页面逻辑
-
pages/index/index.js
文件
1、引入calc.js文件
- 引入
calc.js
文件,获取计算器对象
2、编写页面所需数据
- data里包含了两个数据:
sub
与num
3、设置变量标识
- 设置三个变量标识:
numChangeFlag
、execFlag
、resultFlag
4、编写数字按钮的点击事件处理函数
- 数字按钮的点击事件处理函数 -
btnNum()
- 编译之后,查看预览效果
- 如果不采用条件运算符来处理,就可能出现0打头的数字或一串0
5、编写运算符按钮的点击事件处理函数
- 运算符按钮的点击事件处理函数 -
btnOperate()
6、修改数字按钮点击事件函数代码
- 按了运算符按钮之后,应该输入第二个数字,但是它会接到第一个数字后面,而不是输入第二个数字,为了解决这个问题,我们要在数字按钮点击事件函数里进行判断
- 重新编译,查看编译效果
7、编写等号按钮的点击事件处理函数
-
等号按钮的点击事件处理函数 -
btnCalculate
-
重新编译,查看编译效果
文章来源:https://www.toymoban.com/news/detail-848638.html -
显示算式和计算结果
文章来源地址https://www.toymoban.com/news/detail-848638.html
8、重置按钮(c
按钮)的点击事件处理函数
- 重置按钮的点击事件处理函数 -
btnReset()
- 重新编译,查看预览效果
- 实现了重置按钮功能之后,我们可以进行多次计算
9、小数点按钮的点击事件处理函数
- 小数点的点击事件处理函数 -
btnDot()
- 重新编译,预览效果
10、删除按钮的点击事件处理函数
- 删除按钮的点击事件处理函数-
btnDel()
- 重新编译,查看预览效果
11、正负号切换按钮的点击事件处理函数
- 正负号切换按钮的点击事件处理函数 -
btnPosNeg()
- 重新编译,查看预览效果
12、特殊情况处理
(1)解决不能进行连等计算的问题
- 在计算器理输入“3 + 2 =”,计算结果显示“5”,再次点击“=”,此时,计算结果不会有变化。
- 为了实现连等计算,应该在用户再次点击“=”按钮时,执行“5+2”的计算,就是将运算结果作为第一个数字来进行计算,于是得到结果“7”。
- 修改
btnCalculate()
函数 - 绑定“=”按钮
- 重新编译,查看预览效果
(2)解决数字拼接的问题
- 在计算器中输入“4+5 = ”之后,计算结果显示“9”,再次输入“2 3”时,计算结果显示“923”,如下图所示,显然是不合理的
- 很简单,如果是结果状态,当你在输入数字时,立马将计算器重置。
- 修改
btnNum()
事件处理函数
- 重新编译,检验是否解决了运算结果拼接数字的问题
- 显示了计算结果时,如果再点击数字按钮,不会拼接在计算结果后面,而会显示下一次计算的第一个数字。
(3)解决没有输入第2个数字按等号按钮无法计算的问题
- 在计算器里输入“8 + ”之后,没有输入第2个数字,就去点击等号按钮,没有任何动静,我们希望此时将第一个数字也作为第2个数字参与计算,这样,屏幕就会出现“8 + 8 = ”的计算式与“16”的计算结果。
-
修改ctnCalculate()
函数
- 重新编译,查看预览效果
(4)解决无法通过运算符按钮实现连续计算的问题
- 在计算器里输入“5 + 3”之后,不是点击等号按钮,而是点击其他运算符按钮(减号按钮),这种连续计算,原来的代码搞不定,它是把第二个数字变成了第一个数字来处理,显然不合理,应该把计算结果当成第一个数字来进行处理。
- 修改
btnOperate()
事件处理函数
- 重新编译,查看预览效果
13、查看页面逻辑源码
// index.js
// 引入calc.js文件,获取计算器对象 (calculator)
const calc = require('../../utils/calc')
Page({
// 页面所需数据
data: {
sub: '', //当前计算式
num: '0' //当前计算结果
},
// 设置变量标识
numChangeFlag: false, //值为false,标识当前尚未发生数字切换,值为true,表示切换到第二个数字,切换后在将值设置为false
execFlag: false, //值为false,表示尚未输入第二个数字,值为true,表示已经输入第二个数字
resultFlag: false, //值为false,表示当前处于等待输入状态,值为true,表示当前处于计算结果状态
// 数字按钮点击事件处理函数
btnNum(e) {
// 获取数字按钮对应的数字,赋值给Num
var num = e.target.dataset.val //dataset.val对应按钮的自定义属性data-val
// 如果是结果状态,那么计算器重置
if (this.resultFlag) {
this.btnReset()
}
// 判断是否该输入第二个数字
if (this.numChangeFlag) {
// 将数字切换标识设置为假
this.numChangeFlag = false
// 将execFlag标识设置为真
this.execFlag = true
// 将data.num设置为'0',避免第二个数字拼接到第一个数字后面,而是直接替换
this.data.num = '0'
//切换到第二个数字
calc.changeNum2()
}
//设置输入的数字(条件运算符避免0打头的数字或者一串0的数字出现)
calc.setNum(this.data.num === '0'? num:this.data.num + num)
//在页面显示输入的数字
this.setData ({
num: calc.getNum()
})
},
//运算符按钮的点击事件处理函数
btnOperate(e) {
// 保存上前的运算符
if (calc.op != '') {
var opOld = calc.op
}
//获取运算符按钮对应的运算符,赋给运算器对象的op属性
calc.op = e.target.dataset.val //dataset.val对应按钮的自定义属性data-val
// 将数字切换标识设置为真
this.numChangeFlag = true
// 判断是否已经输入第二个数字
if (this.execFlag) {
// 将输入第二个数字标识变量设置为假
this.execFlag = false
//判断是否为结果状态
if (this.resultFlag) {
// 将结果状态标识变量设置为假
this.resultFlag = false
//TODO
} else { //用户没有点击等号按钮,而是连续点击了运算符按钮
// 此时做连续计算,将计算结果作为第一个数字来处理
// 保存本次运算符
var opNew = calc.op
// 恢复上次运算符来进行计算
calc.op = opOld
calc.num1 = calc.getResult()
// 恢复成本次运算符
calc.op = opNew
}
}
// 刷新页面结果区域的两个数据
this.setData ({
sub: calc.num1 + ' ' + calc.op + ' ' + calc.num2, //当前计算式 ,此时第二个数字为空,等待用户输入
num: calc.num1 //当前计算结果,为什么是第一个数字呢?因为尚未输入第二个数字并且点击等号按钮
})
},
// 等号按钮的点击事件处理函数
btnCalculate () {
// 判断数字是否切换到第二个数字,尚未输入第二个数字
if (this.numChangeFlag) {
// 将数字切换标识变量设置为假
this.numChangeFlag = false
// 准备输入第二个数字,将输入第二个数字的标志变量设置为真
this.execFlag = true
// 将用户输入的第一个数字(显示在结果区域第二行的数字 - 结果)作为第二个数字参与计算
calc.num2 = this.data.num
}
// 判断是否已经输入第二个数字
if(this.execFlag) {
// 设置结果标识为真
this.resultFlag = true
// 调用计算器对象的getResult()函数获取计算结果
var result = calc.getResult()
// 属性页面结果区域的两个数据
this.setData({
sub: calc.num1 + ' ' + calc.op + calc.num2 + ' = ', //当前计算式
num: result //当前计算结果
})
}
// 将运算结果作为第一个数字
calc.num1 = result
},
// 重置按钮的点击事件处理函数
btnReset() {
// 调用计算器模块的事件重置函数
calc.reset()
// 初始化三个变量标识
this.numChangeFlag = false
this.execFlag = false
this.resultFlag = false
this.setData({
sub:'',
num:'0',
})
},
// 小数点按钮的点击事件处理函数
btnDot() {
// 判断是否为结果状态,重置计算器
if (this.resultFlag) {
this.btnReset()
}
// 切换到第二个数字等待输入,设为“0”
if (this.numChangeFlag) {
// 将数字切换标识设置为假
this.numChangeFlag = false
// 将execFlag标识设置为真
this.execFlag = true
// 目标切换到第二个数字
calc.changeNum2()
// 将数字设置为“0.”
calc.setNum('0.')
} else if (this.data.num.indexOf('.') < 0) {
// 当前数字没有“.”,那么将拼接“.”
calc.setNum(this.data.num + '.')
}
// 更新数据,刷新页面
this.setData({
num:calc.getNum()
})
},
// 删除按钮的点击事件处理函数
btnDel() {
// 判断是否为结果状态,重置计算器
if (this.resultFlag) {
this.btnReset()
}
// 非计算状态,将删除当前数字中最右边的一个字符
var num = this.data.num.substring(0,this.data.num.length - 1)
// 判断是否已经删除完有效数字,删完之后,继续按删除按钮,数字将置为0
calc.setNum(num === '' || num === '-' || num === '-0.' ? '0' : num)
// 更新数据,刷新页面
this.setData({
num:calc.getNum()
})
},
// 正负号按钮的点击事件处理函数
btnPosNeg() {
// 针对“0”,不加正负号
if (this.data.num === '0' || this.data.num === '0.') {
return
}
// 如果是结果状态,重置计算器
if (this.resultFlag) {
this.btnReset();
} else if (this.data.num.indexOf('-') < 0) { //数字前没有负号
// 在数字前添加一个“-”号
calc.setNum('-' + this.data.num)
} else { //数字前有负号
// 去掉数字的第一位
calc.setNum(this.data.num.substring(1))
}
// 更新数据,刷新页面
this.setData ({
num:calc.getNum()
})
}
})
到了这里,关于微信小程序案例3-2:计算器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!