目錄
一、引言與效果圖
?二、源碼
0.目錄結(jié)構(gòu):
1.xxxx.wxml文件
?2.樣式文件
(1)xxxx.less文件
(2)xxxx.wxss文件 (不會(huì)使用 less 的可以用這個(gè))
3.xxxx.json文件
4.accurate.js
5.xxxx.js文件
三、結(jié)語(yǔ)
一、引言與效果圖
? ? ? ?最近在做一個(gè)記賬本小程序,其中需要用到計(jì)算器,但是在網(wǎng)上找的代碼,用起來(lái)不是不符合我的想法,就是看著非常難受,于是還是自己寫了一個(gè)
?二、源碼
0.目錄結(jié)構(gòu):
名字 ( test ) 是我隨便取的,你們可以取別的,但是accurate.js的名字請(qǐng)勿改動(dòng)
1.xxxx.wxml文件
對(duì)應(yīng)上方目錄結(jié)構(gòu)的 : test.wxml
<view class="counter">
<view class="result">
<view class="showResult">
<view class="result-num">{{counter.posture[0]}}</view>
<view class="result-num">{{counter.posture[1]}}</view>
<view class="result-num">{{counter.posture[2]}}</view>
</view>
</view>
<view class="btns">
<view class="row">
<view class="col clear" hover-class="hover-bg" bindtap="resetBtn">C</view>
<view class="col" hover-class="hover-bg" bindtap="delBtn">DEL</view>
<view class="col chu" hover-class="hover-bg" bindtap="opBtn" data-val="%">%</view>
<view class="col" hover-class="hover-bg" bindtap="opBtn" data-val="÷">÷</view>
</view>
<view class="row">
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="7">7</view>
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="8">8</view>
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="9">9</view>
<view class="col" hover-class="hover-bg" bindtap="opBtn" data-val="×">×</view>
</view>
<view class="row">
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="4">4</view>
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="5">5</view>
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="6">6</view>
<view class="col" hover-class="hover-bg" bindtap="opBtn" data-val="-">-</view>
</view>
<view class="row">
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="1">1</view>
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="2">2</view>
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="3">3</view>
<view class="col" hover-class="hover-bg" bindtap="opBtn" data-val="+">+</view>
</view>
<view class="row">
<view class="col zero" hover-class="hover-bg" bindtap="numBtn" data-val="0">0</view>
<view class="col" hover-class="hover-bg" bindtap="numBtn" data-val=".">.</view>
<view class="col save" hover-class="hover-bg" bindtap="finish">=</view>
</view>
</view>
</view>
?2.樣式文件
我是用less寫的,所以這里先放less文件(不知道less怎么使用的,可以往下滑,看到wxss文件)
對(duì)應(yīng)上方目錄結(jié)構(gòu)的 : test.wxss 和 test.less
(1)xxxx.less文件
page {
display: flex;
flex-direction: column;
height: 100%;
background-image: linear-gradient(to top, #a8edea 0%, #fed6e3 100%);
}
.counter {
height: 100%;
display: flex;
flex-direction: column;
font-size: 60rpx;
border-top: 1rpx solid #ccc;
border-left: 1rpx solid #ccc;
.result {
flex: 1;
position: relative;
width: 100%;
box-sizing: border-box;
display: flex;
align-items: flex-end;
justify-content: flex-end;
border-bottom: 5rpx solid #d5dde1;
background: rgba(215, 250, 252, 0.253);
.showResult {
display: flex;
align-items: flex-end;
justify-content: flex-end;
flex-wrap: wrap;
font-size: 100rpx;
width: 100%;
box-sizing: border-box;
padding: 20rpx;
.result-num {
overflow-x: auto;
text-align: end;
word-wrap: break-word;
}
}
}
.btns {
flex: 1;
.row {
display: flex;
.col {
flex-basis: 25%;
height: 150rpx;
border-right: 1rpx solid #ccc;
border-bottom: 1rpx solid #ccc;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
font-size: 50rpx;
&.clear {
color: #f00;
}
&.zero {
flex-basis: 50%;
}
&:last-child,
&.chu {
color: #008bfc;
}
&.save {
color: #f90808;
font-size: 80rpx;
font-weight: 900;
}
&.hover-bg {
background: rgba(255, 255, 255, 0.2);
}
}
}
}
}
(2)xxxx.wxss文件 (不會(huì)使用 less 的可以用這個(gè))
page {
display: flex;
flex-direction: column;
height: 100%;
background-image: linear-gradient(to top, #a8edea 0%, #fed6e3 100%);
}
.counter {
height: 100%;
display: flex;
flex-direction: column;
font-size: 60rpx;
border-top: 1rpx solid #ccc;
border-left: 1rpx solid #ccc;
}
.counter .result {
flex: 1;
position: relative;
width: 100%;
box-sizing: border-box;
display: flex;
align-items: flex-end;
justify-content: flex-end;
border-bottom: 5rpx solid #d5dde1;
background: rgba(215, 250, 252, 0.253);
}
.counter .result .showResult {
display: flex;
align-items: flex-end;
justify-content: flex-end;
flex-wrap: wrap;
font-size: 100rpx;
width: 100%;
box-sizing: border-box;
padding: 20rpx;
}
.counter .result .showResult .result-num {
overflow-x: auto;
text-align: end;
word-wrap: break-word;
}
.counter .btns {
flex: 1;
}
.counter .btns .row {
display: flex;
}
.counter .btns .row .col {
transition: all 0.3s;
flex-basis: 25%;
height: 150rpx;
border-right: 1rpx solid #ccc;
border-bottom: 1rpx solid #ccc;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
font-size: 50rpx;
}
.counter .btns .row .col.clear {
color: #f00;
}
.counter .btns .row .col.zero {
flex-basis: 50%;
}
.counter .btns .row .col:last-child,
.counter .btns .row .col.chu {
color: #008bfc;
}
.counter .btns .row .col.save {
color: #f90808;
font-size: 80rpx;
font-weight: 900;
}
.counter .btns .row .col.hover-bg {
background: rgba(255, 255, 255, 0.2);
}
3.xxxx.json文件
對(duì)應(yīng)上方目錄結(jié)構(gòu)的 : test.json
{
"usingComponents": {},
"navigationBarTitleText": "計(jì)算器",
"navigationBarBackgroundColor": "#f4dfe9"
}
4.accurate.js
對(duì)應(yīng)上方目錄結(jié)構(gòu)的 : accurate.js ,請(qǐng)勿改名
這個(gè)文件是用于進(jìn)行精確計(jì)算的:因?yàn)閖s自帶的浮點(diǎn)數(shù)計(jì)算有bug!用這個(gè)函數(shù)進(jìn)行加減乘除,可以防止浮點(diǎn)數(shù)運(yùn)算出現(xiàn)問(wèn)題
module.exports = {
//加法 add
add(arg1, arg2) {
let 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;
},
//減法 subtraction
sub(arg1, arg2) {
let r1, r2, m, n;
try {
r1 = arg1.toString().split(".")[1].length;//獲取小數(shù)點(diǎn)后的長(zhǎng)度
} catch (e) {
r1 = 0;
}
try {
r2 = arg2.toString().split(".")[1].length;//獲取小數(shù)點(diǎn)后的長(zhǎng)度
} 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);
},
//乘法 multiplication
mul(arg1, arg2) {
let 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);
},
//除法 division
div(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);
}
}
5.xxxx.js文件
對(duì)應(yīng)上方目錄結(jié)構(gòu)的 test.js
我的做法是,使用一個(gè)長(zhǎng)度為3的數(shù)組,存儲(chǔ)式子的 “左” “中” “右” 的數(shù)字或操作符,然后再進(jìn)行一些特殊情況的處理
//引入精確計(jì)算的js
const acc = require('./accurate.js');
Page({
data: {
counter: {
posture: ['', '', ''], //存放式子,比如 1 + 12
ansType: false, //判斷是否是手動(dòng)點(diǎn)擊的等于號(hào)
},
},
//輸入數(shù)字
numBtn(e) {
let num = e.currentTarget.dataset.val
let posture = this.data.counter.posture
if (posture[1] === '') { //如果運(yùn)算符為空,就在式子數(shù)組第0個(gè)位置放入內(nèi)容
//判斷特殊情況1: 小數(shù)點(diǎn)
if (num == '.' && posture[0] == '') { //如果是點(diǎn),且字符串為空,就默認(rèn)加上 0
posture[0] = '0'
} else if (num == '.' && posture[0].indexOf('.') > -1) { //如果已經(jīng)有點(diǎn)了還按
console.log('已經(jīng)有點(diǎn),不能再按');
return
}
//判斷特殊情況2:如果是手動(dòng)點(diǎn)了等號(hào)之后,再按數(shù)字,不應(yīng)該在原位置加,而是清空再加 (通過(guò)其它方式比如 “1+2+“ 調(diào)用的finish函數(shù)不算,需要是手動(dòng)點(diǎn)擊的,判斷方法:手動(dòng)點(diǎn)擊的等號(hào)有事件對(duì)象e)
if (this.data.counter.ansType) {
posture[0] = ''
this.setData({
'counter.ansType': false //生效一次即可取消
})
}
//判斷特殊情況3:如果這里面只有0,那么就刪掉這個(gè)0,再增加(想輸入小數(shù)點(diǎn)除外)
if (num !== '.' &&posture[0] == '0') {
posture[0] = ''
}
this.setData({
'counter.posture[0]': posture[0] + num
})
} else { //如果運(yùn)算符不為空,就在式子數(shù)組第2個(gè)位置放入內(nèi)容
//判斷特殊情況: 小數(shù)點(diǎn)
if (num == '.' && posture[2] == '') { //如果是點(diǎn),且字符串為空,就默認(rèn)加上 0
posture[2] = '0'
} else if (num == '.' && posture[2].indexOf('.') > -1) { //如果已經(jīng)有點(diǎn)了還按
console.log('已經(jīng)有點(diǎn),不能再按');
return
}
//判斷特殊情況2:如果這里面只有0,那么就刪掉這個(gè)0,再增加 (想輸入小數(shù)點(diǎn)除外)
if (num !== '.' && posture[2] == '0') {
posture[2] = ''
}
this.setData({
'counter.posture[2]': posture[2] + num
})
}
console.log(this.data.counter.posture);
},
//輸入運(yùn)算符
opBtn(e) {
let op = e.currentTarget.dataset.val
let posture = this.data.counter.posture
if (posture[2] == '') { //如果式子最后一位為空的話,就把符號(hào)放進(jìn)去運(yùn)算符位置
this.setData({
'counter.posture[1]': op
})
} else { //否則就先運(yùn)算,再放進(jìn)去
this.finish()
this.setData({
'counter.posture[1]': op
})
}
console.log(this.data.counter.posture);
},
//運(yùn)算
finish(e) {
let posture = this.data.counter.posture
let left = parseFloat(posture[0] || 0) //左數(shù)字 如果是空字符串就設(shè)置為0
let right = parseFloat(posture[2] || 0) //右數(shù)字 如果是空字符串就設(shè)置為0
let ans = 0 //答案
console.log(left, right);
switch (posture[1]) { //根據(jù)不同運(yùn)算符,進(jìn)行不同的運(yùn)算
case '+':
ans = acc.add(left, right)
break;
case '-':
ans = acc.sub(left, right)
break;
case '×':
ans = acc.mul(left, right)
break;
case '÷':
if (right == 0) { //如果數(shù)字不合規(guī)
wx.showToast({
title: '不能除 0 哦',
icon: 'none'
})
ans = left
} else {
let _ans = acc.div(left, right)
let x = String(_ans).indexOf('.') + 1;
let y = String(_ans).length - x;
if (y > 10) {
ans = _ans.toFixed(10);
} else {
ans = _ans
}
}
break;
case '%':
if (right == 0) { //如果數(shù)字不合規(guī)
wx.showToast({
title: '不能余 0 哦',
icon: 'none'
})
ans = left
} else {
ans = left % right
}
break;
default:
ans = left
break;
}
console.log(ans);
posture = ['' + ans, '', ''] //清空數(shù)組,把答案放在第一位
let ansType = false
if (e) { //如果有事件對(duì)象,說(shuō)明是手動(dòng)點(diǎn)擊的”=“,應(yīng)該加一個(gè)標(biāo)識(shí)符,點(diǎn)了=再點(diǎn)數(shù)字的時(shí)候,應(yīng)該把左邊數(shù)字清空再處理數(shù)字
console.log('手動(dòng)點(diǎn)擊的等于號(hào),后面點(diǎn)擊數(shù)字時(shí),將清空左邊數(shù)字');
ansType = true
}
this.setData({
'counter.posture': posture,
'counter.ansType': ansType
})
},
//清空
resetBtn() {
this.setData({
'counter.posture': ['', '', ''],
})
},
//退位
delBtn() {
let posture = this.data.counter.posture
//從右到左的順序刪除
if (posture[2]) { //如果最后一位不為空,就先刪它
posture[2] = posture[2].substr(0, posture[2].length - 1)
} else if (posture[1]) { //如果符號(hào)位不為空,就刪它
posture[1] = ''
} else if (posture[0]) { //如果第一位不為空,就刪它
posture[0] = posture[0].substr(0, posture[0].length - 1)
} else return //否則就不做事
this.setData({
'counter.posture': posture
})
console.log(this.data.counter.posture);
},
})
三、結(jié)語(yǔ)
這次的小程序源碼分享到此結(jié)束,如果遇到了源碼中出現(xiàn)了什么bug,歡迎在評(píng)論區(qū)指出
如果你有更好的實(shí)現(xiàn)方式,希望大家不吝賜教文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-429832.html
經(jīng)過(guò)評(píng)論區(qū)提醒,已對(duì)除法結(jié)果小數(shù)點(diǎn)后長(zhǎng)度進(jìn)行限制,同時(shí)修改了部分樣式表,使得數(shù)字超長(zhǎng)時(shí)會(huì)自動(dòng)換行文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-429832.html
到了這里,關(guān)于微信小程序計(jì)算器(含源碼)、含js精確運(yùn)算代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!