@~gson/vue-calculator
Version:
A beautiful and functional Vue calculator component with theme customization and keyboard support
209 lines (208 loc) • 6.4 kB
JavaScript
import { useCssVars as B, ref as r, onMounted as O, onUnmounted as S, createElementBlock as w, openBlock as E, createElementVNode as t, createCommentVNode as T, toDisplayString as m } from "vue";
const V = (o, k) => {
const v = o.__vccOpts || o;
for (const [a, n] of k)
v[a] = n;
return v;
}, A = { class: "calculator" }, D = { class: "display-container" }, L = { class: "expression" }, j = {
key: 0,
class: "result"
}, F = { class: "buttons" }, I = {
__name: "App",
props: {
theme: {
type: Object,
default: () => ({
background: "#f5f7fa",
display: "#ffffff",
button: "#ffffff",
operator: {
background: "#a8e6cf",
hover: "#88d7b5"
},
equal: {
background: "#ff9ff3",
hover: "#f368e0"
},
clear: {
background: "#ff7675",
hover: "#d63031"
},
backspace: {
background: "#e0e0e0",
hover: "#d0d0d0"
}
})
},
confirmText: {
type: String,
default: "确认"
}
},
emits: ["confirm"],
setup(o, { emit: k }) {
B((l) => ({
"7a787720": o.theme.background,
"2097c0c0": o.theme.display,
"381b8774": o.theme.button,
"221bd7b6": o.theme.operator.background,
"7054d1b4": o.theme.operator.hover,
"1ffa8c2c": o.theme.equal.background,
e9e34200: o.theme.equal.hover,
"7be33131": o.theme.clear.background,
d617914e: o.theme.clear.hover,
"6ad0debf": o.theme.backspace.background,
"2a57c90b": o.theme.backspace.hover
}));
const v = k, a = r("0"), n = r(""), R = r(""), C = r(""), g = r(""), u = r(!1), i = r("");
O(() => {
window.addEventListener("keydown", x);
}), S(() => {
window.removeEventListener("keydown", x);
});
const s = (l) => {
if (u.value && (a.value = "", u.value = !1), l === ".") {
const e = n.value.split(/[+\-*/()\s]/).pop();
if (e && e.includes("."))
return;
}
a.value === "0" && l !== "." ? a.value = l : a.value += l, n.value += l, b();
}, c = (l) => {
u.value && (u.value = !1), n.value += l, b();
}, p = (l) => {
u.value && (a.value = "", u.value = !1), n.value += l, b();
}, y = (l) => {
try {
return new Function("return " + l)();
} catch {
return NaN;
}
}, b = () => {
if (n.value)
try {
let l = n.value.replace(/×/g, "*").replace(/÷/g, "/");
const e = y(l);
isNaN(e) || (i.value = `= ${e}`);
} catch {
i.value = "";
}
}, N = () => {
if (n.value)
try {
let l = n.value.replace(/×/g, "*").replace(/÷/g, "/");
const e = y(l);
if (isNaN(e)) {
alert("无效的表达式");
return;
}
if (l.includes("/0")) {
alert("除数不能为0"), f();
return;
}
const d = e.toString();
a.value = d, n.value = d, g.value = "", C.value = "", u.value = !0, i.value = d, v("confirm", d);
} catch {
alert("计算错误"), f();
}
}, x = (l) => {
const e = l.key;
/[0-9.]/.test(e) ? s(e) : ["+", "-", "*", "/", "(", ")"].includes(e) ? e === "(" || e === ")" ? p(e) : c(e) : e === "Enter" ? N() : e === "Backspace" ? n.value.length > 0 && (n.value = n.value.slice(0, -1), a.value = a.value.slice(0, -1) || "0", b()) : e === "Escape" && f();
}, q = () => {
n.value.length > 0 && (n.value = n.value.slice(0, -1), a.value = a.value.slice(0, -1) || "0", b());
}, f = () => {
a.value = "0", n.value = "", R.value = "", C.value = "", g.value = "", i.value = "", u.value = !1;
};
return (l, e) => (E(), w("div", A, [
t("div", D, [
t("div", L, m(n.value), 1),
i.value ? (E(), w("div", j, m(i.value), 1)) : T("", !0)
]),
t("div", F, [
t("button", {
onClick: f,
class: "btn clear"
}, "C"),
t("button", {
onClick: e[0] || (e[0] = () => p("(")),
class: "btn operator"
}, "("),
t("button", {
onClick: e[1] || (e[1] = () => p(")")),
class: "btn operator"
}, ")"),
t("button", {
onClick: e[2] || (e[2] = () => c("*")),
class: "btn operator"
}, "×"),
t("button", {
onClick: e[3] || (e[3] = () => s("7")),
class: "btn"
}, "7"),
t("button", {
onClick: e[4] || (e[4] = () => s("8")),
class: "btn"
}, "8"),
t("button", {
onClick: e[5] || (e[5] = () => s("9")),
class: "btn"
}, "9"),
t("button", {
onClick: e[6] || (e[6] = () => c("/")),
class: "btn operator"
}, "/"),
t("button", {
onClick: e[7] || (e[7] = () => s("4")),
class: "btn"
}, "4"),
t("button", {
onClick: e[8] || (e[8] = () => s("5")),
class: "btn"
}, "5"),
t("button", {
onClick: e[9] || (e[9] = () => s("6")),
class: "btn"
}, "6"),
t("button", {
onClick: e[10] || (e[10] = () => c("+")),
class: "btn operator"
}, "+"),
t("button", {
onClick: e[11] || (e[11] = () => s("1")),
class: "btn"
}, "1"),
t("button", {
onClick: e[12] || (e[12] = () => s("2")),
class: "btn"
}, "2"),
t("button", {
onClick: e[13] || (e[13] = () => s("3")),
class: "btn"
}, "3"),
t("button", {
onClick: e[14] || (e[14] = () => c("-")),
class: "btn operator"
}, "-"),
t("button", {
onClick: e[15] || (e[15] = () => s(".")),
class: "btn"
}, "."),
t("button", {
onClick: e[16] || (e[16] = () => s("0")),
class: "btn"
}, "0"),
t("button", {
onClick: q,
class: "btn operator-top"
}, "⌫"),
t("button", {
onClick: N,
class: "btn equal",
style: { "grid-column": "span 1" }
}, m(o.confirmText), 1)
])
]));
}
}, M = /* @__PURE__ */ V(I, [["__scopeId", "data-v-8dc45829"]]);
export {
M as default
};