夏休み記事1件目です
(ホントはchefの記事を書いていたのですが、どうにもエラーが解決できなかったので先にこちらです)
Vue3について調べたり試したりしたことを忘れないように書き留めました。
間違ってるところがありましたら、優しくご指摘していただけると幸いです。
composition APIって?
関数ベースで提供されるAPI郡
まもなくやってくるvue.js3 23ページより
つまり、用意された関数を使っていろいろできる
なんでこれが必要なの?
いままでのVueでは以下のことが問題でした。
- コンポーネントが大きくなるとコードの可読性が落ちる
- テストしにくい
- コード再利用のパターン化がしにくい
- TypeScriptによる型のサポートが受けにくい
今まで、変数の宣言はdata()
でやって、処理する関数は、methods()
で書いていて、コンポーネントを上下に行ったり来たりしていたものが、これで改善されるかんじですかね?
提供される主なAPIの種類
- リアクティブ状態の操作
- コンポーネントの新エントリーポイント
- ライフサイクルフック
- Dependency injection(依存性の注入)
リアクティブとは?
ある変数を書き換えた時に、事前に定めた関係性を元に、他の変数が適切に更新されたり、事前に定めた動作が発動することを「リアクティブである」と言います
きたるべきvue-nextのコアを理解する - そもそも「リアクティブ」とは?リアクティブ状態の操作
API名 | 内容 |
---|---|
reactive | オブジェクトを取得し、元のオブジェクトの反応型プロキシを返す。2.xのVue.observable() と同じ。 |
ref | 内側の値を取得して、反応性があり、変更可能な ref オブジェクトを返す。 |
readonly | オブジェクトまたはrefを取得し、読み込み専用のプロキシを元のオブジェクトに返す。 |
computed | getter関数を受け取り、getterから返された値に対して不変の反応型 ref オブジェクトを返す。 |
watch | watch は特定のデータソースを監視し、別のコールバック関数を適用する。2.x の this.$watch と同じ。 |
watchEffect | 依存関係を反応的に追跡しながら即座に関数を実行し、依存関係が変更された場合はいつでも再実行する。 |
その他にもAPIがあるので気になる方はVue composition APIを見てみてください
ライフサイクルフック
コンポーネントの新エントリーポイントはあとでsetup
でちょこっと触れるので省略します。
今までのものとcomposition APIのライフサイクルフックの対応は以下のようになっています
Vue 2.x | Compostion API |
---|---|
beforeCreate | setup |
created | setup |
beforeMount | onBeforeMount |
beforeUpdate | onBeforeUpdate |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
errorCaptured | onErrorCaptured |
実際に触ってみる
今回はreactive
とref
について見ていきます。
vueのプロジェクトを作成してvue3の各機能が使えるようにvue-next
を追加します
vue create try-composition
cd try-composition
vue add vue-next
早速composition APIを使ってみたいと思います
<template>
<div>{{ count }} {{ object.foo }}</div>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
setup() {
const count = ref(0)
const object = reactive({ foo: 'bar' })
// expose to template
return {
count,
object
}
}
}
</script>
setup
関数はコンポーネント内でコンポジションAPIを使うためのエントリーポイントとして機能するようです。
return
したものがテンプレートのレンダリングコンテキストになるそうです。
これでnpm run serve
すると以下のように表示されます。
ref
を使った場合value
という内部値を指すプロパティーがあります。
これをつかって値の操作ができます。
<template>
<div></div>
</template>
<script>
import { ref } from 'vue'
export default {
setup () {
const count = ref(0)
console.log(count.value)
count.value++
console.log(count.value)
// expose to template
return {
}
}
}
</script>
変更してコンソールを見てみるとこのようになっています。
しっかり値が1プラスされてます。
では、refで宣言したものを再度reactiveで使ったらどうなるでしょうか?
以下のコードで試してみます。
const count = ref(0)
const state = reactive({
count
})
console.log(state.count)
state.count = 1
console.log(count.value)
変更してコンソールを見てみると、このようにcount
に代入されています。
参照渡しされているっぽいですね。
ref
とreactive
の違いは?
ref
とreactive
はどちらもリアクティブなデータを実現するという点では一緒です。
公式のページを見てみると、
The difference between using ref and reactive can be somewhat compared to how you would write standard JavaScript logic:
(翻訳)ref と reactive の違いは、標準的な JavaScript ロジックの書き方と比較すると、多少の違いがあります。
具体的には以下のコードが紹介されています。
// style 1: 別々の変数
let x = 0
let y = 0
function updatePosition(e) {
x = e.pageX
y = e.pageY
}
// --- compared to ---
// style 2: 1つのオブジェクト
const pos = {
x: 0,
y: 0
}
function updatePosition(e) {
pos.x = e.pageX
pos.y = e.pageY
}
対象 | 該当箇所 | 内容 |
---|---|---|
ref | style 1に該当する | 個別に変数宣言する |
reactive | style 2に該当する | オブジェクトでまとめて宣言する |
読んで試した結果、オブジェクトなのか、別々の変数なのかというかんじなのでしょうか?
公式の説明の翻訳は以下のようです。
ref を使用する場合は、スタイル (1) を refs を使用してより冗長な同等のものに大部分を変換しています (プリミティブ値をリアクティブにするため)。
reactive を使うことは、スタイル (2) とほぼ同じです。リアクティブを使ってオブジェクトを作成するだけで、それだけです。
しかし、リアクティブのみにする場合の問題は、合成関数の消費者がリアクティブを保持するためには、返されたオブジェクトへの参照を常に保持していなければならないということです。オブジェクトを破壊したり、拡散したりすることはできません。
まだまだ理解ができていないので、これからもっと調べて試していきたいと思います。
おわりに
自分自身、調べた結果を忘れないために書いたので、間違いなどがあると思います。
もし「ここ違うんじゃ?」などあったら、教えていただけると幸いです。