【初心者です】Vue.js コンポーネントを複数行で使い回したい
Q&A
Closed
解決したいこと
Vue.jsで表計算するアプリを制作中です。
ボタンを押すと入力フォーム内の数値が増減し、その数値の合計を表示するものです。
これを行単位でコンポーネントを作成し、1行しかない表であれば問題無く動作します。
ただし、このコンポーネントを2行目、3行目・・・と使い回そうとすると、思ったとおりに動作しません。
発生している問題・エラー
現状は1行目のボタンを押すと、1行目の入力フォームだけではなく、2行目の入力フォームの数値も増減してしまう状態です。
これを行単位で動作するようにしたいです。
(1行目のボタンを押すと、1行目の入力フォームの数値だけが増減、2行目のボタンであれば、2行目の入力フォームの数値だけが増減するようにしたいです)
※該当するソースコードにはCSSが適用されていないので、表示は崩れています。
該当するソースコード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<!-- Vue.js(開発用) -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<table class="table table-bordered">
<!-- 見出し行 -->
<thead>
<tr>
<th class="col-sm"></th>
<th class="col-lg bg-light">ゲート①</th>
<th class="col-lg">ゲート②</th>
<th class="col-lg bg-light">ゲート③</th>
<th class="col-lg">ゲート④</th>
<th class="col-lg bg-light">ゴール</th>
<th class="col-md">総打数</th>
<th class="col-md bg-light">加算点</th>
<th class="col-md">Total</th>
</tr>
</thead>
<!-- 1行目 -->
<tbody class="counter">
<tr>
<th>A</th>
<th class="bg-light">
<counter-hit v-model="countGate1"></counter-hit>
</th>
<th>
<counter-hit v-model="countGate2"></counter-hit>
</th>
<th class="bg-light">
<counter-hit v-model="countGate3"></counter-hit>
</th>
<th>
<counter-hit v-model="countGate4"></counter-hit>
</th>
<th class="bg-light">
<!-- <counter-hit v-model="countGoalA"></counter-hit> -->
<counter-hit v-model="countGoal"></counter-hit>
</th>
<th>
<!-- <div class="sum">{{ sumA }}</div> -->
<div class="sum">{{ sum }}</div>
</th>
<th class="bg-light">
<div class="addition"></div>
</th>
<th>
<div class="total"></div>
</th>
</tr>
<!-- 2行目 -->
<tr>
<th>B</th>
<th class="bg-light">
<!-- <counter-hit v-model="countGate5"></counter-hit> -->
<counter-hit v-model="countGate1"></counter-hit>
</th>
<th>
<!-- <counter-hit v-model="countGate6"></counter-hit> -->
<counter-hit v-model="countGate2"></counter-hit>
</th>
<th class="bg-light">
<!-- <counter-hit v-model="countGate7"></counter-hit> -->
<counter-hit v-model="countGate3"></counter-hit>
</th>
<th>
<!-- <counter-hit v-model="countGate8"></counter-hit> -->
<counter-hit v-model="countGate4"></counter-hit>
</th>
<th class="bg-light">
<!-- <counter-hit v-model="countGoalB"></counter-hit> -->
<counter-hit v-model="countGoal"></counter-hit>
</th>
<th>
<!-- <div class="sum">{{ sumB }}</div> -->
<div class="sum">{{ sum }}</div>
</th>
<th class="bg-light">
<div class="addition"></div>
</th>
<th>
<div class="total"></div>
</th>
</tr>
</tbody>
</table>
<!-- Test.js -->
<script src="test.js"></script>
</body>
</html>
const counterHit = {
props: ['value'],
methods: {
countUp() {
this.$emit('input', this.value + 1);
},
countDown() {
if ( this.value > 0 ) {
this.$emit('input', this.value - 1);
}
},
},
template: `
<form class="ml-2 mr-2">
打数
<div class="form-group input-group">
<div class="input-group-prepend">
<button type="button" @click="countUp" class="btn btn-primary">+</button>
</div>
<input type="number" v-model="value" min="0" disabled class="form-control">
<div class="input-group-append">
<button type="button" @click="countDown" class="btn btn-secondary">-</button>
</div>
</div>
</form>
`,
};
new Vue({
el: '.counter',
data() {
return {
countGate1: 0,
countGate2: 0,
countGate3: 0,
countGate4: 0,
countGoal: 0,
/* countGoalA: 0,
countGate5: 0,
countGate6: 0,
countGate7: 0,
countGate8: 0,
countGoalB: 0, */
};
},
computed: {
sum() {
return this.countGate1 + this.countGate2 + this.countGate3 + this.countGate4 + this.countGoal;
},
/* sumA() {
return this.countGate1 + this.countGate2 + this.countGate3 + this.countGate4 + this.countGoalA;
},
sumB() {
return this.countGate5 + this.countGate6 + this.countGate7 + this.countGate8 + this.countGoalB;
}, */
},
components: {
'counter-hit': counterHit,
},
});
自分で試したこと
該当するソースコードの中のコメントアウトしてあるコードのように、v-modelの名前を1行目と2行目では別の名前にすると、思ったように動作しました。
しかし、これではコードが長くなるし、これから3行目、4行目・・・と行を増やしていくと、さらにコードが長くなります。
そのため、現実的な方法では無いのかなと感じています。