Help us understand the problem. What is going on with this article?

Vue Composition APIで使えるリアクティブ関連のAPI一覧

Vue Composition APIのリファレンスを見たらリアクティブ周りのAPIが大量に追加されていたのでまとめてみました。

この記事は以下バージョン時点の情報です。

Vue Composition APIのAPI Reference に掲載されているいくつかのAPIは、まだVue2系で使えるComposition APIのプラグイン(vuejs/composition-api)でサポートされていません。
そのAPIについては :warning: マークを末尾につけています。サポート対応状況についてはこちらの記載をもとにしています。

reactive

引数に渡したオブジェクトのリアクティブなプロキシを返します。
Vue2系のVue.observable()と同等の機能です。ネストされたオブジェクトもリアクティブな値として保持されます。

const obj = reactive({
  name: "Foo",
  address: {
    city: "Bar"
  }
})

obj.address.city = "Huga"
console.log(obj.address.city) // Huga

型定義

function reactive<T extends object>(target: T): UnwrapNestedRefs<T>;

ref

プリミティブな値をrefオブジェクトに変換して返します。refオブジェクトはvalueプロパティでリアクティブな値にアクセスできます。
refの値としてオブジェクトが代入されている場合は、reactiveメソッドによってオブジェクトを深くリアクティブにします。

const count = ref(0)
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

型定義

interface Ref<T = any> {
    [RefSymbol]: true;
    value: T;
}

function ref<T extends object>(value: T): T extends Ref ? T : Ref<UnwrapRef<T>>;
function ref<T>(value: T): Ref<UnwrapRef<T>>;
function ref<T = any>(): Ref<T | undefined>;

computed

コールバック関数を受け取り、戻り値をリアクティブでReadonlyなrefオブジェクトとして返します。
refオブジェクトの値は、コールバック関数内にあるリアクティブな値の変化に応じて再計算されます。
(getterとsetterを持つオブジェクトを渡して書き込み可能なrefオブジェクトを作ることもできます)

const count = ref(1)
const plusOne = computed(() => count.value + 1)

console.log(plusOne.value) // 2
count.value++
console.log(plusOne.value) // 3
plusOne.value = 4 // Error

型定義

// read-only
function computed<T>(getter: () => T): Readonly<Ref<Readonly<T>>>

// writable
function computed<T>(options: {
  get: () => T
  set: (value: T) => void
}): Ref<T>

readonly:warning:

オブジェクト(ref or reactive or プレーン)を受け取り、読み取り専用のリアクティブなプロキシを返します。
軽量な独自storeの周りの実装で使えそうです。

※ 2020/07/03現在、vue-composition-apiプラグインではサポートされてません。

const original = reactive({ count: 0 })

const copy = readonly(original)
console.log(copy.count) // 0

original.count++
console.log(copy.count) // 1
console.log(isReactive(copy)) // true
copy.count++ // Error

型定義

function readonly<T extends object>(target: T): Readonly<UnwrapNestedRefs<T>>;

customRef :warning:

依存関係の追跡と更新のトリガーを明示的に制御するカスタマイズされたrefオブジェクトを返します。
限定された用途でリアクティブな値を使いたい時に良さそうです。

※ 2020/07/03現在、vue-composition-apiプラグインではサポートされてません。

// 代入と参照時に必ずconsole.log()を実行するref
const useLoggerRef = (value: string) => {
  return customRef((track, trigger) => ({
    get() {
      console.log(value)
      track()
      return value
    },
    set(newValue: string) {
      console.log(newValue)
      value = newValue
      trigger()
    }
  }))
}

const foo = useLoggerRef("")

foo.value = "Hoge" // console.log("Hoge")が実行される
foo.value = "Bar" // console.log("Bar")が実行される
const bar = foo.value // console.log("Bar")が実行される

型定義

function customRef<T>(factory: CustomRefFactory<T>): Ref<T>

type CustomRefFactory<T> = (
  track: () => void,
  trigger: () => void
) => {
  get: () => T
  set: (value: T) => void
}

markRaw

リアクティブ化されない(プロキシされない)オブジェクトを返します。
適宜markRawを使いプロキシ変換をスキップすることで、不変のデータソースを持つ大規模なリストのレンダリングなどでパフォーマンスを向上させることができます。

const foo = markRaw({
  baz: "baz"
})
const bar = reactive(foo)
isReactive(bar) // false reactive関数を実行してもリアクティブにならない

型定義

function markRaw<T extends object>(value: T): T

shallowReactive

浅いリアクティブなオブジェクトを返します。ネストされたオブジェクトはリアクティブ化されません。

const state = shallowReactive({
  foo: 1,
  nested: {
    bar: 2
  }
})

isReactive(state) // true
isReactive(state.nested) // false

型定義

function shallowReactive<T extends object>(target: T): T;

shallowRef

浅いリアクティブなrefオブジェクトを返します。ネストされたオブジェクトはリアクティブ化されません。

const foo = ref({})
const bar = shallowRef({})

isReactive(foo.value) // true
isReactive(bar.value) // false

型定義

function shallowRef<T>(value: T): T extends Ref ? T : Ref<T>;

shallowReadonly :warning:

浅いreadonlyなオブジェクトを返します。ネストされたオブジェクトはreadonlyになりません。

※ 2020/07/03現在、vue-composition-apiプラグインではサポートされてません。

const state = shallowReadonly({
  foo: 1,
  nested: {
    bar: 2
  }
})

// mutating state's own properties will fail
state.foo++
// ...but works on nested objects
isReadonly(state.nested) // false
state.nested.bar++ // works

型定義

function shallowReadonly<T extends object>(target: T): Readonly<{
    [K in keyof T]: UnwrapNestedRefs<T[K]>;
}>;

toRaw

プロキシされたリアクティブなオブジェクトの生データを返します。

const foo = {}
const reactiveFoo = reactive(foo)

isReactive(toRaw(reactiveFoo)) // false
toRaw(reactiveFoo) === foo // true

型定義

function toRaw<T>(observed: T): T;

unref

引数がrefの場合はref.valueの値を、それ以外だったら引数自体を返します。
val = isRef(val) ? val.value : val の糖衣構文です。

const foo = ref(1)
const bar = 1

unref(foo) // 1
unref(bar) // 1

型定義

function unref<T>(ref: T): T extends Ref<infer V> ? V : T;

toRef

reactiveなオブジェクトの指定のプロパティをrefオブジェクトに変換して返します。
propsの値をリアクティブを切らず、setup関数外のコンポーザブルな関数に渡すときなどに使えます。

const state = reactive({
  foo: 1,
  bar: 2
})

const fooRef = toRef(state, 'foo')
isRef(fooRef) // true

型定義

function toRef<T extends object, K extends keyof T>(object: T, key: K): Ref<T[K]>;

toRefs

reactiveなオブジェクトの全てのプロパティをrefオブジェクトに変換したオブジェクトを返します。

const state = reactive({
  foo: 1,
  bar: 2
})

const stateAsRefs = toRefs(state)
isRef(stateAsRefs.foo) // true
isRef(stateAsRefs.bar) // true

型定義

type ToRefs<T = any> = {
    [K in keyof T]: Ref<T[K]>;
};
function toRefs<T extends object>(object: T): ToRefs<T>;

isRef

refオブジェクトでラップされているかどうかを判定します。

const foo = ref("foo");
const bar = reactive({
  bar: "bar"
});

isRef(foo) // true
isRef(bar) // false

型定義

isRef<T>(value: any): value is Ref<T>;

isReactive

reactiveかどうか判定します。reactiveで作られたオブジェクトをラップしたreadonlyなオブジェクトの場合にもtrueを返します。

const foo = ref("foo");
const bar = reactive({
  bar: "bar"
});
const baz = readonly(bar);
const hoge = readonly(foo)

isReactive(foo) // false
isReactive(bar) // true
isReactive(baz) // true
isReactive(hoge) // false

型定義

function isReactive(value: unknown): boolean;

isReadonly :warning:

オブジェクトがreadonlyかどうか判定します。

※ 2020/07/03現在、vue-composition-apiプラグインではサポートされてません。

const foo = ref("foo");
const bar = reactive({
  bar: "bar"
});
const baz = readonly(bar);

isReadonly(foo) // false
isReadonly(bar) // false
isReadonly(baz) // true

型定義

function isReadonly(value: unknown): boolean;

isProxy :warning:

オブジェクトがProxyか判定します。reactiveかreadonlyで作成したオブジェクトが該当します。

※ 2020/07/03現在、vue-composition-apiプラグインではサポートされてません。

const foo = ref("foo");
const bar = reactive({
  bar: "bar"
});
const baz = readonly(bar);

isProxy(foo) // false
isProxy(bar) // true
isProxy(baz) // true

型定義

function isProxy(value: unknown): boolean;

終わりに

以上「Vue Composition API v1-beta で使えるリアクティブ関連のAPI一覧」でした。思った以上にAPIが多いですね。
業務ではref, reactive, toRef, toRefs, isRefくらいしか使ってなかったです。
今後はどんどん活用していきたいです。

参考

ryo2132
Frontend engineer / フルリモートワーク / 元消防士🚒 / 一児の父 / Ruby / Typescript / Vue.js / Firebase
admin-guild
「Webサービスの運営に必要なあらゆる知見」を共有できる場として作られた、運営者のためのコミュニティです。
https://admin-guild.slack.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away