20
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

VueCompostionAPIにおける refとreactiveの使い方について

Last updated at Posted at 2019-11-17

はじめに

前回の記事からの続きになります

Vue3.xから採用予定のCompositionAPIとVue2.xを比較してみる

前回の記事を書いた際にrefreactiveの違いについて

これらについてはまだ実装しながら確認している最中なので、また別途まとめたいと思います。

と記載していました。
今回はそれらについて実装を進めつつまた残しておきたいと思います。

なお確認の際に実装したソースコードは以下のgithubにあげています。
vue-composition-api-test

前提とする環境

VueCLI v4.0.5
node v10.16.0
yarn v1.13.0

CompositionAPIのリアクティブなオブジェクト

compostionAPIでリアクティブなオブジェクトを定義する場合、refとreactiveの2種類があります。
それらについてふれていきます。

refについて

refは単一のvalueプロパティをもつプリミティブオブジェクトです。
イメージ的には以前data()で定義されていたものが近いです。

呼び出しかた

vue2.x系で使用する場合はcompositionAPIからインポートします。

HelloRef.vue
import { createComponent, ref } from "@vue/composition-api";

定義のしかた

setup()関数内で以下のように変数を定義します。

HelloRef.vue
const RefHelloCount = ref(1);

配列を定義することも可能です。

HelloRef.vue
const Animals = ref(["cat", "dog", "hamster"]);

以下のようなデータを定義する場合は後述のreactiveを使用します。

HelloRef.vue
let RefAnimalObjects = ref({
  cat: 1,
  dog: 2
});

値へのアクセス方法

変数の値には、setup()関数内のメソッドなどで呼び出す場合は変数名.valueで、テンプレートからはそのまま{{変数名}}で呼び出します。

それぞれ確認していきます、

setup()関数内での呼び出し

数字を増加させるだけのメソッドを導入してみます。
以下のように記述すると失敗します。

HelloRef.vue
const incrementHello = () => {
   RefHelloCount++;
};

なぜならrefで定義された変数はプリミティブなオブジェクトであるからです。
consoleに出力してみたデータを確認したところ以下のような表示になります。

スクリーンショット 2019-11-15 20.59.20.png

そのため先ほどの処理を以下のように修正します。

HelloRef.vue
const incrementHello = () => {
    refHelloCount.value++;
};

これで問題なく動作します。

templateでの呼び出し

tempalteへの表示を行う際にはvalueの表記はせずに記載しても問題なく表示がなされます。
APIの内部でvalueexposeするような処理が走っているのでvalueなしの状態で記載します。

HelloRef.vue
<p>{{ RefHelloCount }}</p>

注意点

  • setup関数内で呼び出す際の扱い方とtemplate内での呼び出し方の違い
    • templateないで呼び出すときはvalueがなくても大丈夫。API側がよしなに変更してくれる
    • setup関数内で呼び出すときはvalueが必要
  • オブジェクトを定義する場合はreactiveを使用する

reactive

もう一つのreactiveを確認します。
こちらもrefと同じようにcomposition-apiからインポートします。

HelloRef.vue
import { createComponent, reactive } from "@vue/composition-api";

定義のしかた

先ほど一つ一つrefにで定義して分散して記載していたものをまとめることができます。
returnする際にも定義した一つの変数を記載すればすみます。

HelloRef.vue
const ReactiveData = reactive({
    count: 1,
    ReativeAnimals: ["cat", "dog", "hamster"]
});

return {
    ReactiveData
};

値へのアクセス方法

上記のように定義した場合、setup()関数内で使用する場合は変数名.keyでアクセスします。テンプレート変数で利用する場合も変数名.key(valueは不要)でアクセスをします。

それぞれ確認していきます。

setup()関数内での呼び出し

変数名.keyで該当の値にアクセスします。
なおこの際にvalueは不要です。

この点に関してはrefで作成したデータにアクセスするよりはシンプルでわかりやすいように思えます。

HelloRef.vue
const incrementHelloReactve = () => {
    ReactiveData.count++;
};

templateでの呼び出し

値へのアクセスで触れましたが、template内で該当の変数を呼び出すのにrefに比べて冗長になりがちです。

HelloRef.vue

return {
    ReactiveData
};

↓ 上記データをtemplate内で使用する

<p>
    {{ReactiveData.count}}
    {{ReactiveData.animals}}
</p>

そこでこのオブジェクトをプレーンなオブジェクトに変換するtoRefsというメソッドを利用します。

これを利用するとそれぞれのプロパティがplainなオブジェクトに変換され、templateから呼び出す際に冗長な書き方が不要になります。

return {
    ...toRefs(ReactiveData)
};

return分の中で上記のように記載するとtemplate内での記述が以下のように変わります。

<p>
    {{count}}
    {{animals}}
</p>

非常にシンプルになりました。

API内部で何をやっているのか

compostionAPIの内部で何をやっているのか確認してみました。
node_modules/@vue/compostion-api/vue-composition-api.module.js
174行目から191行目にそれらしき記述があります。

composition-api
function isPlainObject(x) {
    return toString(x) === '[object Object]';
}

function toRefs(obj) {
    if (!isPlainObject(obj))
        return obj;
    var res = {};
    Object.keys(obj).forEach(function (key) {
        var val = obj[key];
        // use ref to proxy the property
        if (!isRef(val)) {
            val = createRef({
                get: function () { return obj[key]; },
                set: function (v) { return (obj[key] = v); },
            });
        }
        // todo
        res[key] = val;
    });
    return res;
}

isPlainObjectでオブジェクトかどうかを判別して、該当していた場合は渡されobjforEachで回してgetter,setterを定義してやっているようです。

まとめ

最後までお読みいただきありがとうございます。
refとreactiveの違いについてざっくりと確認してきました。

ここまで触ってきての印象はrefで定義する変数は他と関連性が薄いもの、独立しているものが適しているように感じます。
かたやreactiveに関していうと、一つの変数の中にkey:valueの形でそれぞれが関連するものとして定義した方がいいものが適していると感じます。
例えばユーザーの情報など。

例:

const User = reactive({
    name: 'Taro',
    age: '19',
    sex: 'male'
})

まだcompostionAPI自体ドキュメントが揃いきっているわけではないので、どのように運用していくのがいいのか、個人のプロダクトなどに突っ込んでいくことで判断していきたいと思います。

参考

20
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?