[vue2] 一个很简易的计算器

622 阅读1分钟

image.png

目前实现的功能: 1.X后退一步,C全部清除 2.支持小数点 3.一次运算输出一个结果,再次运算是与上一次的结果

核心代码:

<template>
    <div
        class="calculator_wrap"
        :style="{ color: expenseFontColor }"
        @click="clickKeyboard"
    >
        <img :src="expenseKeyboardBg" alt="" v-if="expenseKeyboardBg" />
        <img src="../../assets/images/home/skin/skin5-3/bg.jpg" alt="" v-else />
        <div class="content">
            <div class="calculator_temp">
                <span>{{ temp ? temp : "0.00" }}</span>
            </div>
            <div
                v-for="(item, index) in arr"
                :key="index"
                class="calculator_row"
            >
                <div
                    v-for="(item2, index2) in item"
                    :key="index2"
                    class="calculator_col"
                    :style="{ 'background-color': item2.color }"
                    @click="handleCalculator"
                >
                    <div>{{ item2.value }}</div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import { mapActions, mapState } from "vuex";
export default {
    props: {
        money: {
            type: Number,
            default: 0,
        },
        show: {
            type: Boolean,
            default: false,
        },
        currency: {
            type: String,
            default: "CNY",
        },
        clickable: {
            type: Boolean,
            default: true,
        },
    },
    computed: {
        ...mapState({
            expenseKeyboardBg: (state) =>
                state.systemSettings.expenseKeyboardBg,
            expenseKeyboardSound: (state) =>
                state.systemSettings.expenseKeyboardSound,
            expenseFontColor: (state) => 
                state.systemSettings.expenseFontColor,
        }),
    },
    data() {
        return {
            result: 0,
            temp: "",
            operator: "",
            arr: [
                [
                    { value: "7" },
                    { value: "8" },
                    { value: "9" },
                    { value: "+" },
                    { value: "X" },
                ],
                [
                    { value: "4" },
                    { value: "5" },
                    { value: "6" },
                    { value: "-" },
                    { value: "C" },
                ],
                [
                    { value: "1" },
                    { value: "2" },
                    { value: "3" },
                    { value: "*" },
                    { value: "取消", color: "yellow" },
                ],
                [
                    { value: "货币", color: "green" },
                    { value: "0" },
                    { value: "." },
                    { value: "/" },
                    { value: "完成", color: "yellow" },
                ],
            ],
        };
    },
    methods: {
        ...mapActions({
            asyncPlaySound: "keyboard/asyncPlaySound",
        }),
        handleCalculator(e) {
            if (!this.clickable) {
                return;
            }
            const choice = e.target.innerText;
            switch (true) {
                case /^X$/.test(choice):
                    this.temp = this.temp.slice(0, this.temp.length - 1) || "";
                    break;
                case /^C$/.test(choice):
                    this.temp = "";
                    break;
                case /取消/.test(choice):
                    this.$emit("handleCancel");
                    break;
                case /完成/.test(choice):
                    if (this.temp !== "") {
                        if(isNaN(Number(this.temp))){
                            this.temp = this.temp.slice(0, this.temp.length - 1);
                        }
                        this.temp = Number(this.temp).toFixed(2);
                    } else {
                        this.temp = "0.00";
                    }
                    this.$emit("handleConfirm", this.temp);
                    break;
                case /^货币/.test(choice):
                    this.chooseCurrency();
                    break;
                case /^=/.test(choice):
                    this.temp = eval(this.temp).toFixed(2);
                    this.changeCompleteBtn("完成")
                    break;
                default:
                    if (!this.checkValid(choice)) {
                        return;
                    }
                    //要先输入数字
                    if (this.temp === "" &&["+", "-", "*", "/"].indexOf(choice) != -1) {
                        return;
                    }
                    if (
                        this.arr[3][4].value === "=" &&
                        ["+", "-", "*", "/"].indexOf(choice) != -1
                    ) {
                        this.temp = eval(this.temp).toFixed(2);
                    }
                    this.temp += choice;
                    break;
            }
        },
        chooseCurrency() {
            this.$emit("showMoneyType");
        },
        changeCompleteBtn(str) {
            this.arr[3][4].value = str;
        },
        checkValid(choice) {
            //1. 不允许输入3.00..
            if (/\d+\.\d\d$/.test(this.temp) && choice == ".") {
                return false;
            }
            //2.  限制用户输入的是两位小数
            if (
                /\d+\.\d\d$/.test(this.temp) &&
                choice >= "0" &&
                choice <= "9"
            ) {
                return false;
            }
            //3. 不允许输入两个操作符
            if (
                ["+", "-", "*", "/"].indexOf(this.temp[this.temp.length - 1]) != -1 &&
                ["+", "-", "*", "/"].indexOf(choice) != -1
            ) {
                this.temp = this.temp.substring(0, this.temp.length - 1);
            }
            return true;
        },
        //按下键盘上的某一个键
        clickKeyboard() {
            if (this.expenseKeyboardSound) {
                this.asyncPlaySound();
            }
        },
    },
    watch: {
        temp: function (val) {
            if (/(\d+\.?)[+\-*/](\d+\.?)/.test(val)) {
                this.changeCompleteBtn("=");
            }else{
                this.changeCompleteBtn("完成");
            }
        },
        show: function (newVal, oldVal) {
            if (newVal && !oldVal) {
                if (this.temp == "0.00") {
                    this.temp = "";
                }
            }
        },
        currency: function (val) {
            this.arr[3][0].value = "货币" + val;
        },
    },
    created() {
        this.arr[3][0].value = "货币" + this.currency;
    },
};
</script>

<style scoped>
.calculator_wrap {
    width: 100%;
    height: 4rem;
    padding-bottom: 0.15rem;
    position: relative;
}
.calculator_wrap .content{
    position: absolute;
    top: 0;
    left: 0;
    z-index: 10;
    width: 100%;
    height: 100%;
}
.calculator_wrap img {
    position: absolute;
    opacity: 0.5;
    top: 0;
    left: 0;
    z-index: 9;
    width: 100%;
    height: 100%;
}
.calculator_wrap .calculator_row {
    display: flex;
}
.calculator_wrap .calculator_col {
    width: 20%;
    height: 0.8rem;
    border: 0.04rem solid #c7c7c7;
    border-radius: 0.1rem;
    display: flex;
    align-items: center;
    justify-content: center;
}
.calculator_wrap .calculator_temp {
    height: 0.8rem;
    text-align: right;
    line-height: 0.8rem;
    border-bottom: 0.02rem solid #c7c7c7;
    margin-bottom: 0.01rem;
}
.calculator_wrap .calculator_temp span {
    display: inline-block;
    margin-right: 0.2rem;
    font-size: 0.4rem;
}
</style>

事件:

handleConfirm - 确认键盘输入

handleCancel - 取消键盘输入

handleMoneyType - 打开币种选择

props:

money - 初始金额

show - 键盘显示

currency - 币种简称,如CNY

clickable - 键盘是否可点击