あっくんブログ Written by Akihiro Tsuji

Vue3で計算アプリケーションを作ろう

Vue.js プログラミング

こんにちは、あっくんです。職業訓練を終了して、就活しながら家で勉強をしています。職業訓練では椅子に座って机で勉強をしていました。僕は普段スタンディングデスクを使って、立って勉強をしていて久しぶりにがっつり立って勉強をしていると立っていることができなくなっていました。立ったままでいる筋肉の耐久性がなくなったんだなと思いました。立って勉強するほうが集中しやすいと言われています。僕はじっとしていられないので立って勉強をするほうがやりやすいです。おすすめのスタンディングデスクです。↓

今回は、Vue3で計算アプリケーションをつくっていきましょう。やっぱりJavaScriptの理解が必要ですね。

Calcコンポーネントで計算

今回は計算アプリケーションを作っていきましょう。計算式を書いてボタンを押すと答えを表示するというものを作っていきましょう。

Image from Gyazo

↑「Clear Log」ボタンを押し、ダイアログでOKするとログが消去されます。

変数が使える。

例えば

tax = 8
price = 12500
price * (1.0 + tax / 100)

税額を変数taxに、金額をpriceにそれぞれ設定しておき、それらを使った計算式を最後に書くとpriceの税込み価格を計算して表示されます。

ログが表示される

計算を実行すると、その結果を記録し、下に表示するようにしています。最大10個まで記憶しておくようにしています。「Clear Log」ボタンでログを消去できます。

作成するプログラムの内容

まずプロジェクトを立ち上げます。今回はcalc_appという名前でやっていきましょう。ターミナルでプロジェクトを作成するディレクトリに移動して↓を実行します・

npm init vite-app calc_app

そして必要なパッケージをインストールしましょう。
ターミナルでcalc_appをカレントディレクトリにしてnpmをインストールします。

cd calc_app

npm install

今回は2つのコンポーネントを作成します。

App.vue

プロジェクトに作成されているもの。コンポーネントのベースになるもの。

Calc.vue

新たに作成するもの。計算の実行部分を担当するコンポーネント。

App.vueはそのまま使用します。Calc.vueは「components」フォルダの中に新たにファイルを作成して使います。

Calc.vueを作成する

「components」フォルダの中に「Calc.vue」というファイルを用意します。

Image from Gyazo

↑新しいファイルアイコンでファイルを作成します。

Calc.vueのソースコード

<template> <div class="card alert-primary"> <div class="card-body text-left"> <h2 class="card-title text-center">{{ title }}</h2> <p class="card-text h5">{{ message }}</p> <hr /> <div> <div class="form-group"> <label>Formula:</label> <textarea class="form-control mb-2" v-model="fomula"></textarea> </div> <div class="text-center"> <button class="btn btn-primary" v-on:click="doAction">CALC</button> </div> </div> </div> </div> </template> <script> export default { name: "Calc", props: { title: String, }, data() { return { message: "Enter expression:", fomula: "0", }; }, methods: { doAction() { let arr = this.fomula.trim().split("\n"); let last = arr.pop(); let fn = ""; for (let n in arr) { if (arr[n].trim() != "") { fn += "let " + arr[n] + ";"; } } fn += "return " + last + ";"; let exp = "function f(){" + fn + "} f();"; let ans = eval(exp); this.message = "answer: " + ans; let re = arr.join(";").trim(); if (re != "") { re += ";"; } re += last; this.$emit("result-event", re, ans); }, }, }; </script>
Code language: HTML, XML (xml)

Clacの構成

<h2>{{ title }}{{ message }}</p>

先ずテンプレートでtitleとmessageを表示しています。

<div class="form-group"> <label>Formula:</label> <textarea class="form-control mb-2" v-model="fomula"></textarea> </div> <div class="text-center"> <button class="btn btn-primary" v-on:click="doAction">CALC</button> </div>
Code language: HTML, XML (xml)

式を入力するテキストエリアと実行ボタンを設置しています。<textarea>ではv-model=”fomula”としてfomulaという変数に値が同期されるようにしています。ボタンはv-on:click=”doAction”として、クリックするとdoActionが実行されるようにしてあります。

コンポーネントに用意されるもの

まず、propsとdataで用意される値です。

props: { title: String, }, data() { return { message: "Enter experssion", fomula: "0", }; },
Code language: JavaScript (javascript)

propsにはtitleをdataではmessageとfomulaをそれぞれ用意しています。これらがテンプレートで表示されます。titleは後で変更することがないので、属性として設定できるようにpropsにしてありますが、messageとfomulaは常に変更されものであるため、dataに用意しています。

doActionの処理について

methodsにはボタンをクリックしたときに実行されるdoActionが用意されています。テキストエリアに記述された値(v-modelでfomulaに値が保管されています)をもとに、入力された式を実行し結果を取り出しています。
↓のような流れで行っています。

1.fomulaのテキストを改行コードで分割し配列にする
let arr = this.fomula.trim().spli('\n')

2.配列の最後の項目を変数lastに取り出しておく(配列からは消える)
let last = arr.pop()

3.配列の各要素について繰り返し処理をする
for(let n in arr) {

4.繰り返しでは、取り出した項目のテキストが空でないなら、「let テキスト;」というテキストを作って変数fnに追加する
if (arr[n].trim() != '') {
fn += 'let' + arr[n] + ';'
}

5.繰り返しが終わったら、「return最後の項目;」とテキストを追加してテキストを完成
fn += 'return' + last + ';'

6.完成したテキストの前後に「function(){」「}fn;」と付け足す。これで、取り出した処理のテキストをfという関数にまとめて実行するスクリプトができあがる
let exp = 'function f() {' + fn + '} f();'

7.eval関数を使って、スクリプトのテキストを実行する
let ans = eval(exp)

8.実行結果をメッセージにまとめてmessageに設定
this.message = 'anser:' + ans

9.配列をセミコロン(;)記号でつなげて1つのテキストにする
let re = arr.join(';').trim()

10.配列が空でなければセミコロンを付け、最後の項目を付け加える
if(re != '') { re += ';'}
re += last

11.作成したテキストを引数に指定し、$emitでresult-eventイベントを呼び出す
this.$emit('result-event', re, ans)

入力テキストは関数として実行

複数行に渡る計算の場合は、それらをJavaScriptとして正しく実行できるようにしておく必要があります。書いた式全体を関数にまとめ、その関数を実行するようにします。つまり、テキストの最初にfunction○○(){とつけ、最後に}とつければ、関数の形になります。そして、関数に書かれたテキストは、変数に代入する文の場合は「let ○○ = ☓☓;」という形にして、最後の計算式は 「return ○○」という形にしてJavaScriptとして実行できます。

例、

a = 100 b = 200 a + b

function f() { let a = 100 let b = 200 return a + b+ } f()
Code language: JavaScript (javascript)

これで実行すればa + bの計算結果が得られます。後は、入力された式を1つのテキストにまとめて、result-eventイベントを呼び出しています。計算結果をログとして保管し管理するのは、これresult-eventで呼び出されるApp側の役割になります。

Appコンポーネントを作る

<template> <div id="app"> <Calc v-bind:title="message" v-on:result-event="appAction" /> <div class="mt-3 text-left"> <table class="table" v-html="log"></table> </div> <div> <button class="btn btn-danger" v-on:click="doClear">Clear Log</button> </div> </div> </template> <script> import Calc from "./components/Calc.vue"; export default { name: "App", components: { Calc, }, data() { return { message: "CALC", result: [], }; }, computed: { log() { let table = "<tr><th>Expression</th><th>Value</th></tr>"; if (this.result.length > 0) { for (var i in this.result) { table += "<tr><td>" + this.result[i][0] + "</td><th>" + this.result[i][1] + "</th></tr>"; } } return table; }, }, created() { let items = localStorage.getItem("log"); let logs = JSON.parse(items); if (logs != null) { this.result = logs; } }, methods: { appAction(exp, res) { this.result.unshift([exp, res]); var log = JSON.stringify(this.result); localStorage.setItem("log", log); }, doClear() { if (confirm("ログをすべて消去します。")) { localStorage.removeItem("log"); this.result = []; } }, }, }; </script>
Code language: HTML, XML (xml)

Appコンポーネントの構成

<Calc v-bind:title="message" v-on:result-event="appAction" />

まずはテンプレートにv-bindでmessageという値にバインドしています。また、v-onで、result-eventイベントが発生したら、appActionメソッドを呼び出します。

<div> <tablev-html="log"></table> </div>
Code language: HTML, XML (xml)

tableタグにはv-htmlを使い、logの値を表示するようにしています。

用意される値について

components: { Calc, }, data() { return { message: "CALC", result: [], }; },
Code language: JavaScript (javascript)

Calcコンポーネントを組み込み、dataにはmessageとresultの2つの値を用意しています。messageは、<Calc>タグのv-bind:titleに設定してあります。resultは実行した式と結果を配列にまとめて保管するものです。

算出プロパティ


computed: { log() { let table = "ExpressValue"; if (this.result.length > 0) { for (var i in this.result) { table += "" + this.result[i][0] + "" + this.result[i][1] + ""; } } return table; }, },
Code language: JavaScript (javascript)

logは、this.resultの配列から順に値を取り出し、その内容をテーブルのタグの形にまとめて作成してあります。resultは「配列の配列」になっています。実行した式と、その結果の2つの値をまとめた配列を、更に配列にまとめて設定しています。つまり、forを使って配列の要素を順に取り出したら、その取り出した配列から、更に値を取り出して利用することになります。

初期化処理created

created() { let items = localStorage.getItem("log"); let logs = JSON.parse(items); if (logs != null) { this.result = logs; } },
Code language: JavaScript (javascript)

createdは初期化処理に関するものです。これは、コンポーネントのオブジェクトが作成された直後に実行されます。つまりこのcreatedに処理を用意することで、propsなどの設定を上書きして変更できます。

ローカルストレージについて

localStrageというのは,ローカルストレージというものを利用するためのオブジェクトです。これは、Webブラウザに値を保管するのにもちいられます。getItemは、指定のキーを取り出すメソッドです。

変数 = localStorage.getItem(キー)

JSON.parseでオブジェクトに変換

取り出したテキストはJSONオブジェクトの「parse」というメソッドでオブジェクトにしています。JSONはJSON形式のデータを取り扱うための昨日を提供するもので、parseは引数のテキストをもとに、JavaScriptのオブジェクトを生成します。

appActionメソッドについて

1.引数を配列resultに追加する
this.result.unshift([exp, res])

unshiftは配列の最初に値を追加するメソッドです。

2.配列reusltをJSONテキストに変換する
var log = JSON.stringify(this.result)

stringifyは引数のオブジェクトをJSON形式のテキストに変換します。これで、this.resultの配列がテキストに変換されます。

3.ローカルストレージに保存する
localStrage.setItem('log', log)

loclaStrageオブジェクトの「setItem」メソッドで、作成されたテキストをlogというキーに保存します。setItemは、値を指定の名前でローカルストレージn保存するメソッドです。

localStorage.setItem(キー, 値)

doClearメソッドについて

if (confirm("ログをすべて消去します。")) {  localStorage.removeItem("log");  this.result = []; }
Code language: JavaScript (javascript)

confirmがOKならば、trueをキャンセルなfalseを返します。つまり、OKならばローカルストレージからログデータを消去します。localStrageの「removeItem」は、引数に指定したキーの値を削除するメソッドです。配列を保管しているresultも一緒に操作する必要があります。

Image from Gyazo

ここまで読んでいただいてありがとうございます。今回は難しかったです。掌田津耶乃さんのVue.js3超入門で勉強をしています。語りかけるような文章ですごいわかりやすいです。本当におすすめです。