vueのコードを修正する
半年ほど前に、栄養価を確認できるレシピサイトをつくりました。
その為にがむしゃらに書きちらしてしまったコードを改善していきます。
この記事はその第一弾。
修正元のコード
初回なので、今回は修正元のコードを公開するだけにとどめておきます。
修正するのは以下のコード。
PostEditPage.vue
<template>
<div class="PostEditPage">
<form>
<div v-if="errors.length != 0">
<ul v-for="e in errors" :key="e">
<li>
<font color="red">{{ e }}</font>
</li>
</ul>
</div>
<h2>レシピ編集</h2>
<div>
<label>レシピ名</label><br />
<input v-model="post.rname" type="text" />
</div>
<div>
<label>レシピ情報</label><br />
<textarea v-model="post.rinformation"></textarea>
</div>
<div>
<label>レシピイメージ</label><br />
<input type="file" name="rimage" @change="selectedFile" />
</div>
<div>
<label>材料</label><br />
<textarea v-model="post.ingredient"></textarea>
</div>
<div>
<label>手順1</label><br />
<textarea v-model="post.procedure_1"></textarea>
</div>
<div>
<label>手順2</label><br />
<textarea v-model="post.procedure_2"></textarea>
</div>
<div>
<label>手順3</label><br />
<textarea v-model="post.procedure_3"></textarea>
</div>
<div class="form-row">
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>エネルギー</label><br />
<input v-model="post.Energy" type="number" step="0.01" />kcal
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>タンパク質</label><br />
<input v-model="post.Protein" type="number" step="0.01" />g
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>脂質</label><br />
<input v-model="post.Lipid" type="number" step="0.01" />g
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>糖質</label><br />
<input v-model="post.Carbohydrate" type="number" step="0.01" />g
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>食物繊維</label><br />
<input v-model="post.Dietary_fiber" type="number" step="0.01" />g
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>カリウム</label><br />
<input v-model="post.Potassium" type="number" step="0.01" />mg
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>カルシウム</label><br />
<input v-model="post.Calcium" type="number" step="0.01" />mg
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>鉄</label><br />
<input v-model="post.iron" type="number" step="0.01" />mg
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>亜鉛</label><br />
<input v-model="post.Zinc" type="number" step="0.01" />mg
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>ビタミンa</label><br />
<input v-model="post.VitaminA" type="number" step="0.01" />μg
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>ビタミンb1</label><br />
<input v-model="post.VitaminB1" type="number" step="0.01" />mg
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>ビタミンb2</label><br />
<input v-model="post.VitaminB2" type="number" step="0.01" />mg
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>ビタミンc</label><br />
<input v-model="post.VitaminC" type="number" step="0.01" />mg
</div>
<div class="co-xs-2 col-sm-2 col-md-2 col-lg-2">
<label>塩分相当量</label><br />
<input v-model="post.Salt_equivalent" type="number" step="0.01" />g
</div>
</div>
<div v-show="show">
<div>
<button class="button" type="button" @click="Reflect_Nutrients(post)">
材料を反映
</button>
<p>利用する材料の栄養合算</p>
<table class="table table-sm">
<thead>
<tr>
<th scope="col">エネルギー</th>
<th scope="col">タンパク質</th>
<th scope="col">脂質</th>
<th scope="col">糖質</th>
<th scope="col">食物繊維</th>
<th scope="col">カリウム</th>
<th scope="col">カルシウム</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ addNutrients.Energy }}kcal</td>
<td>{{ addNutrients.Protein }}g</td>
<td>{{ addNutrients.Lipid }}g</td>
<td>{{ addNutrients.Carbohydrate }}g</td>
<td>{{ addNutrients.Dietary_fiber }}g</td>
<td>{{ addNutrients.Potassium }}mg</td>
<td>{{ addNutrients.Calcium }}mg</td>
</tr>
</tbody>
</table>
<table class="table table-sm">
<thead>
<tr>
<th scope="col">鉄</th>
<th scope="col">亜鉛</th>
<th scope="col">ビタミンa</th>
<th scope="col">ビタミンb1</th>
<th scope="col">ビタミンb2</th>
<th scope="col">ビタミンc</th>
<th scope="col">塩分相当量</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ addNutrients.iron }}mg</td>
<td>{{ addNutrients.Zinc }}mg</td>
<td>{{ addNutrients.VitaminA }}μg</td>
<td>{{ addNutrients.VitaminB1 }}mg</td>
<td>{{ addNutrients.VitaminB2 }}mg</td>
<td>{{ addNutrients.VitaminC }}mg</td>
<td>{{ addNutrients.Salt_equivalent }}g</td>
</tr>
</tbody>
</table>
</div>
<div>
<p>利用する材料</p>
<ul
v-for="(item, index) in ingrd_sum"
v-bind:class="['q_' + index]"
:key="item.id"
>
<li>{{ item.rname }}</li>
<input v-model="$data['q_' + index]" />
</ul>
</div>
<div>
<input type="text" v-model="keyword" />
<button class="button" type="button" @click="filteredPosts">
検索
</button>
<ul v-for="post in posts" :key="post.id">
<li>{{ post.rname }}</li>
<button class="button" type="button" @click="add_ingredient(post)">
材料に追加
</button>
</ul>
</div>
</div>
<button type="button" class="button" @click="show = !show">
既存のレシピを材料に加える
</button>
</form>
<br />
<button class="button" v-on:click.preventDefault="updatePost">
Commit
</button>
</div>
</template>
<script>
import axios from "axios";
export default {
data: function () {
return {
show: false,
q_0: "1",
q_1: "1",
q_2: "1",
q_3: "1",
q_4: "1",
q_5: "1",
q_6: "1",
q_7: "1",
q_8: "1",
q_9: "1",
q_10: "1",
post: {
rname: "",
rinformation: "",
rimage: "",
ingredient: "",
procedure_1: "",
procedure_2: "",
procedure_3: "",
Energy: "",
Protein: "",
Lipid: "",
Carbohydrate: "",
Dietary_fiber: "",
Potassium: "",
Calcium: "",
iron: "",
Zinc: "",
VitaminA: "",
VitaminB1: "",
VitaminB2: "",
VitaminC: "",
Salt_equivalent: "",
},
posts: [],
ingrd_sum: [],
keyword: "",
errors: "",
uploadFile: null,
};
},
mounted() {
const url = location.pathname;
const id = url.replace(/[^0-9]/g, "");
console.log(`this.post_1: ${JSON.stringify(this.post)}`);
axios
.get(`/api/v1/posts/${id}.json`)
.then((response) => (this.post = response.data));
console.log(`this.post_2: ${JSON.stringify(this.post)}`);
},
computed: {
addNutrients: function () {
let sum_nutrients = {
Energy: "0",
Protein: "0",
Lipid: "0",
Carbohydrate: "0",
Dietary_fiber: "0",
Potassium: "0",
Calcium: "0",
iron: "0",
Zinc: "0",
VitaminA: "0",
VitaminB1: "0",
VitaminB2: "0",
VitaminC: "0",
Salt_equivalent: "0",
};
let sn_keys = Object.keys(sum_nutrients);
for (let i in this.ingrd_sum) {
console.log(`i: ${i}`);
console.log(`this.ingrd_sum[i]: ${JSON.stringify(this.ingrd_sum[i])}`);
let ingrd = this.ingrd_sum[i];
console.log(`ingrd: ${JSON.stringify(ingrd)}`);
console.log(`sum_nutrients: ${JSON.stringify(sum_nutrients)}`);
if (i == 0) {
var bfr_num3 = this.q_0;
} else if (i == 1) {
var bfr_num3 = this.q_1;
} else if (i == 2) {
var bfr_num3 = this.q_2;
} else if (i == 3) {
var bfr_num3 = this.q_3;
} else if (i == 4) {
var bfr_num3 = this.q_4;
} else if (i == 5) {
var bfr_num3 = this.q_5;
} else if (i == 6) {
var bfr_num3 = this.q_6;
} else if (i == 7) {
var bfr_num3 = this.q_7;
} else if (i == 8) {
var bfr_num3 = this.q_8;
} else if (i == 9) {
var bfr_num3 = this.q_9;
} else if (i == 10) {
var bfr_num3 = this.q_10;
} else {
var bfr_num3 = 1;
}
console.log(`bfr_num3: ${JSON.stringify(bfr_num3)}`);
for (let i = 0; i < 14; i++) {
console.log(`sum_nutrients: ${JSON.stringify(sum_nutrients)}`);
console.log(`i: ${i}`);
let sn_key = sn_keys[i];
console.log(`sn_key: ${sn_key}`);
let num1 = parseFloat(sum_nutrients[sn_key]);
let num2 = parseFloat(ingrd[sn_key]);
let num3 = parseFloat(bfr_num3);
if (Number.isNaN(num2)) {
num2 = 0;
}
if (num3 < 0 || 1000 < num3) {
num3 = 1;
} else {
num2 = num2 * num3;
console.log(`num2x: ${JSON.stringify(num2)}`);
}
console.log(`num1: ${JSON.stringify(num1)}`);
console.log(`num2: ${JSON.stringify(num2)}`);
sum_nutrients[sn_key] = num1 + num2;
console.log(
`sum_nutrients[sn_key]: ${JSON.stringify(sum_nutrients[sn_key])}`
);
}
}
return sum_nutrients;
},
},
methods: {
selectedFile(e) {
console.log(e.target.files[0]);
e.preventDefault();
this.uploadFile = e.target.files[0]; // fileにはreadonly制約があり、v-modelは使えない。代わりにchangeイベントが推奨されている
},
add_ingredient: function (post) {
this.ingrd_sum.push(post);
},
Reflect_Nutrients: function (post) {
console.log(`this.post.Energy: ${this.post.Energy}`);
console.log(`this.sum_nutrients: ${JSON.stringify(this.sum_nutrients)}`);
this.post.Energy = this.addNutrients.Energy;
this.post.Protein = this.addNutrients.Protein;
this.post.Lipid = this.addNutrients.Lipid;
this.post.Carbohydrate = this.addNutrients.Carbohydrate;
this.post.Dietary_fiber = this.addNutrients.Dietary_fiber;
this.post.Potassium = this.addNutrients.Potassium;
this.post.Calcium = this.addNutrients.Calcium;
this.post.iron = this.addNutrients.iron;
this.post.Zinc = this.addNutrients.Zinc;
this.post.VitaminA = this.addNutrients.VitaminA;
this.post.VitaminB1 = this.addNutrients.VitaminB1;
this.post.VitaminB2 = this.addNutrients.VitaminB2;
this.post.VitaminC = this.addNutrients.VitaminC;
this.post.Salt_equivalent = this.addNutrients.Salt_equivalent;
},
filteredPosts: function (keyword) {
if (this.keyword === "") {
posts = null;
} else
axios
.get("/api/v1/posts/refer/" + this.keyword)
.then((response) => (this.posts = response.data));
},
updatePost: function () {
const data = new FormData(); // multipart/form-data形式のため、new FormData()を使う
data.append("rname", this.post.rname); // file形式以外も送信可能
data.append("rinformation", this.post.rinformation); // file形式以外も送信可能
data.append("ingredient", this.post.ingredient); // file形式以外も送信可能
data.append("procedure_1", this.post.procedure_1); // file形式以外も送信可能
data.append("procedure_2", this.post.procedure_2); // file形式以外も送信可能
data.append("procedure_3", this.post.procedure_3); // file形式以外も送信可能
data.append("rimage", this.uploadFile);
data.append("Energy", this.post.Energy); // file形式以外も送信可能
data.append("Protein", this.post.Protein); // file形式以外も送信可能
data.append("Lipid", this.post.Lipid); // file形式以外も送信可能
data.append("Carbohydrate", this.post.Carbohydrate); // file形式以外も送信可能
data.append("Dietary_fiber", this.post.Dietary_fiber); // file形式以外も送信可能
data.append("Potassium", this.post.Potassium); // file形式以外も送信可能
data.append("Calcium", this.post.Calcium); // file形式以外も送信可能
data.append("iron", this.post.iron); // file形式以外も送信可能
data.append("Zinc", this.post.Zinc); // file形式以外も送信可能
data.append("VitaminA", this.post.VitaminA); // file形式以外も送信可能
data.append("VitaminB1", this.post.VitaminB1); // file形式以外も送信可能
data.append("VitaminB2", this.post.VitaminB2); // file形式以外も送信可能
data.append("VitaminC", this.post.VitaminC); // file形式以外も送信可能
data.append("Salt_equivalent", this.post.VitaminC); // file形式以外も送信可能
const url = location.pathname;
const id = url.replace(/[^0-9]/g, "");
axios
.patch(`/api/v1/posts/${id}`, data)
.then((response) => {
let e = response.data;
window.location = `/posts/${id}`;
})
.catch((error) => {
console.error(error);
if (error.response.data && error.response.data.errors) {
this.errors = error.response.data.errors;
}
});
},
},
};
</script>