過去のコードをComposition APIを使って書き直してみる(後編)
前回の記事では、前編としてComposition APIについてまとめました。
Composition APIの基本的なsyntaxが分かったところで、実際に当ブログでご紹介した以下の記事のコードをComposition APIを用いて書き直してみたいと思います。
JavaScriptフレームワークの「Vue.js」を使ってToDoリストを実装してみよう(後編)
後編執筆までの間にVue3が公開されました!
※本記事は前回構築した「Vue2.x + @vue/composition-api」の環境で記載しています。
対象のコード
Vue-cliに載せ替える
過去記事のコードはhtml、js、cssの3ファイルで構成されていますので、まずはSFC(SingleFileComponents)化していきます。
前回記載の方法で設置したvue-cliにToDoコンポーネントを作成し、各ファイルを <template> 、 <script> 、 <style> に移植して行きます。
現在の構成は以下のようになっています。
project-dir
└ src
├ main.ts
├ App.Vue
└ components
└ ToDo.vue
ToDo.vueは以下のようになりました。
※長くなってしまうので、script部分のみになります。
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
data: () => {
return {
addText: "",
list: [],
uniqueKey: 0
};
},
methods: {
addToDo(): void {
if (this.addText) {
this.list.unshift({
text: this.addText,
id: this.uniqueKey + 1,
flag: true
});
}
this.addText = "";
this.uniqueKey++;
},
deleteToDo(id: number): void {
let deleteIndex = "";
const check = confirm("本当に削除しますか?");
if (check) {
this.list.some(function(value, index) {
if (value.id === id) {
deleteIndex = index;
}
});
this.list.splice(deleteIndex, 1);
}
},
editToDo(id: number): void {
const newText = window.prompt("以下内容で更新します。");
if (!newText) {
alert("入力欄が空欄です。");
} else {
this.edit(id, newText);
}
},
edit(id: number, text: string): void {
let editIndex = "";
this.list.some(function(value, index) {
if (value.id === id) {
editIndex = index;
}
});
this.list[editIndex].text = text;
},
changeToDo(id: number): void {
let changeIndex = "";
this.list.some(function(value, index) {
if (value.id === id) {
changeIndex = index;
}
});
this.list[changeIndex].flag = this.change(changeIndex);
},
change(changeIndex: number): boolean {
if (this.list[changeIndex].flag) {
return false;
} else {
return true;
}
}
}
});
</script>
Composition APIを用いて書き直し
次にComposition APIを用いて書き直します。
少しリファクタリングを行いましたが、ロジック自体は過去記事のものと同じになっています。
<script lang="ts">
import { defineComponent, reactive, ref } from "@vue/composition-api";
type List = {
text: string;
flag: boolean;
};
export default defineComponent({
setup() {
// data
const addText = ref<string>("");
const list = reactive<List[]>([]);
// method
const add = (): void => {
if (addText.value) {
list.splice(list.length + 1, 1, {
text: addText.value,
flag: true
});
addText.value = "";
}
};
const remove = (key: number): void => {
const check = confirm("本当に削除しますか?");
if (check) {
list.splice(key, 1);
}
};
const edit = (key: number): void => {
const newText = window.prompt("以下内容で更新します。");
if (!newText) {
alert("入力欄が空欄です。");
return;
}
list[key].text = newText;
};
const change = (key: number): void => {
list[key].flag = !list[key].flag;
};
return {
addText,
list,
add,
remove,
edit,
change
};
}
});
</script>
関数の切り出し
次に見通しを良くするために関数を切り出します。
this が無いのですんなり切り出すことができました。
<script lang="ts">
import { defineComponent, reactive, ref } from "@vue/composition-api";
type List = {
text: string;
flag: boolean;
};
const Add = (list: List[]) => {
const addText = ref<string>("");
const add = (): void => {
if (addText.value) {
list.splice(list.length + 1, 1, {
text: addText.value,
flag: true
});
addText.value = "";
}
};
return {
addText,
add
};
};
const Remove = (list: List[]) => {
const remove = (key: number): void => {
const check = confirm("本当に削除しますか?");
if (check) {
list.splice(key, 1);
}
};
return {
remove
};
};
const Edit = (list: List[]) => {
const edit = (key: number): void => {
const newText = window.prompt("以下内容で更新します。");
if (!newText) {
alert("入力欄が空欄です。");
return;
}
list[key].text = newText;
};
return {
edit
};
};
const Change = (list: List[]) => {
const change = (key: number): void => {
list[key].flag = !list[key].flag;
};
return {
change
};
};
export default defineComponent({
setup() {
const list = reactive<List[]>([]);
const { addText, add } = Add(list);
const { remove } = Remove(list);
const { edit } = Edit(list);
const { change } = Change(list);
return {
addText,
list,
add,
remove,
edit,
change
};
}
});
</script>
別ファイルへ切り出し
最後に各関数を別ファイルに切り出します。
現在の構成は以下のようになっています。
project-dir
└ src
├ main.ts
├ App.Vue
├ components
│ └ ToDo.vue
├ types
│ └ List.ts
└ functions
├ Add.ts
├ Remove.ts
├ Edit.ts
└ Change.ts
各種functionは前項でdefineComponentの外に切り出したものを、そのままファイルに切り出しただけになります。
// 例:Add.ts
import { ref } from "@vue/composition-api";
import { List } from "@/types/List.ts";
export const Add = (list: List[]) => {
const addText = ref<string>("");
const add = (): void => {
if (addText.value) {
list.splice(list.length + 1, 1, {
text: addText.value,
flag: true
});
addText.value = "";
}
};
return {
addText,
add
};
};
最終的にToDo.vueは以下のようになりました。
別ファイルに切り出した関数をimportして使う形になっています。
とても見通しよくなったかと思います。
<script lang="ts">
import { defineComponent, reactive } from "@vue/composition-api";
// 各種functionをimport
import { List } from "@/types/List.ts";
import { Add } from "@/functions/Add.ts";
import { Remove } from "@/functions/Remove.ts";
import { Edit } from "@/functions/Edit.ts";
import { Change } from "@/functions/Change.ts";
export default defineComponent({
setup() {
const list = reactive<List[]>([]);
// functionを定義
const { addText, add } = Add(list);
const { remove } = Remove(list);
const { edit } = Edit(list);
const { change } = Change(list);
return {
addText,
list,
add,
remove,
edit,
change
};
}
});
</script>
まとめ
Vue3ではVue2.xと同様にOption APIを使ってコードを書くこともできますが、Composition APIを使って書くことでコードの切り出しや共通化がしやすくなります。
Vue3に対応していないmoduleでもOptions APIであればほぼそのまま使用可能ですが、Composition APIだと基本的には使えない(使えたとしてもComposition APIの利点を消してしまう)という問題もあります。
この記事を書いた人
-
東京で2年半エンジニアとしての経験を積み、浜松にUターンの後、アーティスへ入社。
ソリューション事業部のWebエンジニアとして、システムの設計・開発・保守・運用からインフラまで幅広く従事している。
フルスタックエンジニア目指して現在も勉強の日々。車が好き。
この執筆者の最新記事
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー