Vue3のComposition APIを使おう
こんにちは、あっくんです。Googleアナリティクスのことをよくわかっていないですが、自分の作ったアプリケーションをGoogleアナリティクスで検証できるようにしたいと思い、Googleタグマネージャの設定を行ってHTMLのheadとbodyにGoogleタグマネージャのタグを貼り付けてGoogleアナリティクスとトラッキングコードと紐付けてできました。普通に嬉しかったです。自分のアプリケーション自体訪問数ほぼゼロなのですが、就活でアプリケーションを見ていただいているか気になったので、設置してみました。
今回はCompositon APIを使っていきましょう。
コンポーネントは複雑すぎる
コンポーネントはprops,data,算出プロパティ,ウォッチャ,methodsなどのメソッドで、きれいに組み立てるのが思ったよりも大変です。複雑になりすぎたコンポーネントの問題を解消するためにVue3の開発チームが作り出した仕組みが「Composition API」です。
propsとsetupだけ!
Composition APIは散らばった要素をもう一度1つにまとめ直すことを考えて作られました。
export default {
props: 値,
setup(props) {
…..処理……..
}
}
Code language: CSS (css)
propsはコンポーネントのタグに設定できる属性を管理します。それ以外はsetupで処理します。
コンポーネントを作ってみる。
Composition APIを作ってコンポーネントを作成しましょう。composition_appプロジェクトをViteで作ってやっていきましょう。
開発するディレクトリでターミナルに↓のように記述してcomposition_appを作って、npmをインストールします。
npm init vite-app composition_app
cd composition_app
npm install
srcにあるcomponentsのHelloWorld.vueを書き換えましょう。
<template>
<div class="alert alert-primary">
<h1>{{ title }}</h1>
<p>{{ msg }}</p>
</div>
</template>
<script>
export default {
props: {
title: String,
msg: String,
},
setup(props) {
console.log(props);
},
};
</script>
Code language: HTML, XML (xml)
ここでは、propsにtiteとmsgの2つの属性を用意し、setupでは、propsの値をconsole.logに出力しています。これでデベロッパーツールのコンソールでpropsの内容が確認できます。
HelloWorldを表示する
App.vueとindex.htmlを書き換えます。
<template>
<div id="app">
<HelloWorld title="Composition API" msg="This is Composition API sample." />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "app",
components: {
HelloWorld,
},
};
</script>
Code language: HTML, XML (xml)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Compositon API App</title>
<!-- CSS only -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
crossorigin="anonymous"
/>
<!-- JavaScript Bundle with Popper -->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW"
crossorigin="anonymous"
></script>
</head>
<body>
<h1 class="bg-secondary text-white h4 p-3">Vue3 Composition API</h1>
<div class="container">
<div id="app"></div>
</div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
20210915
↑HelloWorldコンポーネントを表示します。
ここでは、<HelloWorld />タグにtitleとmsgという属性を用意しています。これがHelloWorldのpropsに渡され、{{}}で表示しています。
JSXでも使える?
componentsフォルダ内に「Hello.jsx」を作成して確認していきましょう。
export default {
name: 'HelloJSX',
props: {
title: String,
msg: String
},
setup(props) {
return () => <div class="alert alert-primary">
<h1>{props.title}</h1>
<p>{props.msg}</p>
</div>
}
}
Code language: JavaScript (javascript)
JSXを使うときreturnにアロー関数を用意します。
これを表示するために、App.vueを修正します。
<template>
<div id="app">
<HelloJSX title="Composition API" msg="This is Composition API sample." />
</div>
</template>
<script>
import HelloJSX from "./components/HelloJSX.jsx";
export default {
name: "app",
components: {
HelloJSX,
},
};
</script>
Code language: HTML, XML (xml)
↑JSXで表示できました。
setupのreturnについて
setupではreturnを書く場合もあります。returnした内容をもとにコンポーネントを表示されるのです。.vueファイルも、setupのrerturnで表示内容を返す関数を用意することもできます。
<template>
<div class="alert alert-primary">
<h1>{{ title }}</h1>
<p>{{ msg }}</p>
</div>
</template>
<script>
import { h, ref } from "vue";
export default {
props: {
title: String,
msg: String,
},
setup(props) {
return () =>
h("div", { class: "alert alert-primary" }, [
h("h1", props.title),
h("p", props.msg),
]);
},
};
</script>
Code language: HTML, XML (xml)
dataではなく、refを使います
コンポーネントで一番多用するのはdataの値です。しかし、「Composition API」ではdataはありません。ではどうやって、テンプレート側で利用する値を用意しますか。それは、「ref」を使って、変数として用意します。「ref」は値の参照を作成するためのものです。参照とは、その値を指し示す値のことです。つまり、その値が保管されている場所を示す値です。
変数 = ref(値)
リアクティブな値として使うためには、refを使って値を用意する必要があります。
refで値を用意する
setup(props) {
const 定数= ref (値
return {定数
}
Code language: JavaScript (javascript)
setpu内でrefを使って参照を作成し、それをreturnでオブジェクトにまとめて返すようにします。この返されたオブジェクトに用意された値が、テンプレートで利用できるようになるのです。
refで値を表示する
HelloWorld.vueをrefを使って記述していきましょう。App.vueはHelloWorldを表示するように記述します。
<template>
<div class="alert alert-primary">
<h1>{{ title }}</h1>
<p>{{ data.msg }} ({{ data.count }})</p>
</div>
</template>
<script>
import { ref } from "vue";
export default {
props: {
title: String,
},
setup(props) {
const data = ref({
msg: "This is ref-value!",
count: 0,
});
setInterval(() => {
data.value.count++;
}, 1000);
return {
data,
};
},
};
</script>
Code language: HTML, XML (xml)
<template>
<div id="app">
<HelloWorld title="Composition API" msg="This is Composition API sample." />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "app",
components: {
HelloWorld,
},
};
</script>
Code language: HTML, XML (xml)
↑表示すると数字がカウントされていきます。
refによる参照の利用
setup(props) {
const data = ref({
msg: "This is ref-value!",
count: 0,
})
Code language: JavaScript (javascript)
refを使って、dataという定数を作成しています。このrefの引数にはmsg,countという2つのオブジェクトを用意しています。作成された定数は、returnで返します。
return {
data
}
Code language: JavaScript (javascript)
これでテンプレート側で利用できるようになります。
<p>{{ data.msg }} ({{ data.count }}) </p>
これでrefで作成された値が利用できるようになります。
スクリプト側で参照を使う場合
setInterval(() => {
data.value.count++
}, 1000)
Code language: JavaScript (javascript)
値を1増やしている部分は、data.count++ではなく、data.value.count++です。dataは値そのものではなく参照であるので、refで参照している値はvalueというメソッドで得ることができます。つまり、data.valueでdataが参照しているオブジェクトを取り出せるようになっています。
refとreactive
先程のrefによる参照はスクリプトないで利用するときはvalueを使う必要がありました。スクリプトとテンプレートの値の記述がことなるので、わかりにくいです。
スクリプト内
data.value.count
テンプレート内
data.count
参照を作成するのは 「ref」以外に「reactive」という関数があります。
変数 = reactive(値)
このreactiveは「リアクティブ可能な値のコピー」を返すものです。値をコピーをしてリアクティブになります。
HelloWorld.vueをreactiveを使って記述しましょう。
<template>
<div class="alert alert-primary">
<h1>{{ title }}</h1>
<p>{{ data.msg }} ({{ data.count }})</p>
</div>
</template>
<script>
import { ref, reactive } from "vue";
export default {
props: {
title: String,
},
setup(props) {
const data = reactive({
msg: "This is ref-value!",
count: 0,
});
setInterval(() => {
data.count++;
}, 1000);
return {
data,
};
},
};
</script>
Code language: HTML, XML (xml)
↑先程と同様に数字がカウントされていきます。
reactiveではスクリプト内で値を利用する部分がわかりやすくなります。
setInterval(() => {
data.count++
}, 1000)
Code language: JavaScript (javascript)
テンプレートでの利用と書き方が同じになります。ただし、reactiveで作成できるのはオブジェクトのみです。数字や真偽値のような基本型の値は使えないです。がーんです。refは基本型の値でもすべて参照として取り出すことができます。
基本型の値をリアクティブにしたいときはref
オブジェクトをリアクティブにしたいときはreactiveと考えるといいかもしれません。
メソッドの利用
メソッドの利用は、setup内で変数に関数を代入しておき、この変数をテンプレートに割り当てます。HelloWorld.vueを書き換えてみましょう。
<template>
<div class="alert alert-primary">
<h1>{{ title }}</h1>
<p class="h5">{{ data.msg }}</p>
<div>
<input type="number" v-model="data.num" min="0" class="form-control" />
</div>
<button class="btn btn-primary m-3" v-on:click="action">Click</button>
</div>
</template>
<script>
import { ref, reactive } from "vue";
export default {
props: {
title: String,
},
setup(props) {
const data = reactive({
msg: "This is ref-value!",
nmu: 0,
});
const action = () => {
let total = 0;
for (let i = 1; i <= data.num; i++) {
total += i;
}
data.msg = "Total:" + total;
};
return {
data,
action,
};
},
};
</script>
Code language: HTML, XML (xml)
↑数字を入力してクリックすると、その数字までの合計を計算して表示します。
setup内にaction関数を用意します。
const action = () => {
let total = 0
for (let i = 1; i <= data.num; i++) {
total += i
}
data.msg = "Total:" + total
}
Code language: JavaScript (javascript)
アロー関数を定数に代入する形で用意しています。
return {
data,action
}
Code language: JavaScript (javascript)
これで、dataとactionがテンプレートで使えるようになります。
<button class=”btn btn-primary m-3″ v-on:click=”action”>Click </button>
v-on:clickにactionを指定することで、クリックすると定数actionに代入された関数が実行されます。
setupのcntextについて
setupメソッドでは、引数にpropsが渡されました。これ以外に「context」という引数が渡されます。
contextはコンポーネントに関する情報をひとまとめにしたオブジェクトです。↓のような項目が含まれています。
attrs
コンポーネントタグに用意された属性をまとめたもの
slots
コンポーネント内に含まれるスロットをまとめたもの
emit
emitされた内容をまとめたもの
これらはcontext.attrsというような形でアクセスし値を得ることができます。HelloWorld.vueを修正していきましょう。
<template>
<div class="alert alert-primary">
<h1>{{ title }}</h1>
<p class="mt-3 h5">{{ data.msg }}</p>
</div>
</template>
<script>
import { ref, reactive } from "vue";
export default {
props: {
title: String,
},
setup(props, context) {
const data = reactive({
msg: "This is ref-value!",
});
data.msg = context.attrs["msg"].toUpperCase();
return {
data,
};
},
};
</script>
Code language: HTML, XML (xml)
↑msg属性がすべて大文字になってメッセージが表示されます。
context.attrs[‘msg’]という形でmsg属性の値を取得し、それをtoUpperCaseですべて大文字にした値をdata.msgに設定してテンプレートで表示させています。
ここまで読んでいただいてありがとうございます。
今回はComposition APIについて、data,methods,
computed等を使わないでpropsとsetup(props, context)を使って記述することがわかりました。setupを使って記述がきれいになるようにということですが、もっとコードを書いて感覚的につかみたいです。
掌田津耶乃さんのVue.js3超入門で勉強をしています。語りかけるような文章ですごいわかりやすいです。本当におすすめです。