などの疑問や悩みを解決してまいります。
この記事ではVue.jsでref
とreactive
を使ってみてリアクティブな変数を作成し、2つの違いについて理解することができます。
初心者向けの記事となっていますので予めご了承ください。
リアクティブな値とは何か
リアクティブな値は、その値の変更がされるとそれに応じて他の部分も自動的に更新されるという特徴を持っています。
例えばフォームに入力した内容を別の箇所にも同時に反映するといったことも可能になります。
値をリアクティブにするためにはref
とreactive
を使用します。
どのような違いがあるのか、そして使い方について参考例を交えて解説していきたいと思います。
refを使ったパターン
まずはref
を使ったパターンから解説していきます。
ref
はref
関数を使用して、単一な値をリアクティブにすることができます。
単一とはつまり配列やオブジェクトではない値をリアクティブにしたい場合にref
関数を使用するということになります。
実際に使用例を紹介します。
今回2つのVueファイルを用意しました。ページに表示するApp.vueとコンポーネントファイルのLearnVue.vueです。
<script setup>
import LearnVue from './components/LearnVue.vue';
</script>
<template>
<LearnVue />
</template>
<style scoped></style>
<script setup>
import { ref } from 'vue';
const inputValue = ref('')
const input = (e) => {
inputValue.value = e.target.value
}
</script>
<template>
<input @input="input" type="text">
<label>入力した内容:{{ inputValue }}</label>
</template>
<style scoped></style>
ハイライトしているコードがref
に関係する部分になります。
このコードでページを確認すると以下のような実装が可能になります。
それではコードの説明していきます。
ref関数をインポートする
それではscript
タグの中から見ていきます。
<script setup>
import { ref } from 'vue';
const inputValue = ref('')
const input = (e) => {
inputValue.value = e.target.value
}
</script>
まずref関数を使用するためにはimport { ref } from 'vue';
のコードが必要になります。
このコードはComposition APIから ref
関数をインポートしている部分になります。
なのでref
を使って単一な値をリアクティブにしたい場合は、まずこの記述からといった感じです。
リアクティブな値にしたい内容をラップする
今回の例ではconst inputValue = ref('')
と記述しています。
これは定数inputValue
の値をref
関数でラップしてリアクティブな値としています。
関数の引数に入れていると解釈されてしまいがちですが、ref
関数はラップされたデータを返すのではなく、その格納されたデータをオブジェクトとして値を返します。
ref
関数の()内に入れた値をラップすると説明しています。どのようなオブジェクトで返ってくるかは後ほど説明します。
ref関数でラップした値にアクセスする場合
次に着目していただきたいのがinput
関数の処理内容です。
input関数はフォームに入力があったらinputValue.value = e.target.value
このコードの処理をするように記述しています。
左から見ていきます。
inputValue.value
というのは結論から言うとinputValue
の値にアクセスすることです。
ref
関数はラップされたデータを返すのではなく、その格納されたデータをオブジェクトとして値を返すということを前の題で説明しました。
オブジェクトの値にアクセスするために.value
を使っているということです。
今回のref
関数によって返ってくる値は以下のようになります。
{ value: '入力された文字列' }
.value
でアクセスしているんですね!これにより、inputValue.value
でアクセスして、値を代入しているということになります。
入力した値を取得
次に右側のコードを見ていきます。
e.target.value
は入力した値を取得します。
まずe
はevent
の略でイベントオブジェクトです。
.target
はそのイベントオブジェクトの数あるプロパティの1つでありイベントが発生した要素を取得します。
ここでe.target
をconsole.log
で出力すると以下の値が返ってきます。
<input type="text">
input
イベントが発生した要素を取得できていますね。.value
はフォーム要素から値を取得するためのプロパティです。
なのでe.target.value
はイベントが発生したフォーム要素(inputタグ)の入力した内容を取得するというコードになります。
inputイベントで関数の処理を発生、値をマスタッシュ構文へ
script
タグ内の解説が終了したということでtemplate
タグ内を見ていきます。
<input @input="input" type="text">
はv-onディレクティブでinput
を指定しています。
これでフォームに入力されたらイベントが発火するようになっています。
発火したときに走る処理がinput
関数です。
input関数は入力した値を定数inputValue
に代入していましたね。
その代入された定数inputValue
の内容をマスタッシュ構文でページに表示されるようにしています。
リアクティブな値はその値が変更されるごとにDOMを再構築します。
なので今回の場合はフォームに1文字追加されるごと関数の処理が走りリアクティブな値が更新されます。
更新されるごとにDOMが再構築されてマスタッシュ構文内の内容も更新されていくという仕組みになっています。
reactiveを使ったパターン
次にreactive
を使ってリアクティブな値を作っていきます。
reactive
はreactive
関数を使用してオブジェクト全体をリアクティブな値とします。
reactive
を使用したコード例を以下に準備しています。
<script setup>
import { reactive } from 'vue';
const profile = reactive({
name: '',
age: 0
})
const inputName = (e) => {
profile.name = e.target.value
}
const inputAge = (e) => {
profile.age = e.target.value
}
</script>
<template>
<input @input="inputName" type="text" placeholder="名前の入力"><br>
<label>名前:{{ profile.name }}</label><br>
<input @input="inputAge" type="number" placeholder="年齢の入力"><br>
<label>年齢:{{ profile.age }}</label>
</template>
<style scoped></style>
今回は名前の入力欄に文字列を入力すると名前:の箇所に入力した内容が表示されます。
また年齢の入力欄に数字を入力すると年齢:の箇所に入力した数値が表示されます。
ページには以下のように表示されます。
それではコードの説明していきます。
reactive関数をインポートする
<script setup>
import { reactive } from 'vue';
const profile = reactive({
name: '',
age: 0
})
const inputName = (e) => {
profile.name = e.target.value
}
const inputAge = (e) => {
profile.age = e.target.value
}
</script>
まずreactive
関数を使用するためには、ref
関数同様import { reactive } from 'vue';
のコードが必要になります。
reactive
関数もref
と同様にComposition APIから インポートしてくる必要があります。
なのでオブジェクトをリアクティブな値としたい場合はこのコードを最初に記述しておきましょう。
reactive関数でオブジェクトをラップする
こちらもref
関数同様にリアクティブな値としたいオブジェクトをラップします。
const profile = reactive({
name: '',
age: 0
})
値にアクセスする場合は、通常のオブジェクトと同様にnameの値にアクセスする場合はprofile.name
、ageの値にアクセスする場合はprofile.age
とします。