# ref 関連
このセクションでは、コード例に 単一ファイルコンポーネント 構文を使用します
# ref
内部の値を受け取り、リアクティブでミュータブルな ref オブジェクトを返します。ref オブジェクトには、内部の値を指す単一のプロパティ .value
があります。
例:
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
2
3
4
5
ref の値としてオブジェクトが割り当てられている場合、そのオブジェクトは reactive 関数によってディープなリアクティブになります。
型:
interface Ref<T> {
value: T
}
function ref<T>(value: T): Ref<T>
2
3
4
5
場合によっては、ref の内部値に複合の型を指定する必要があります。そのような場合には、ref
を呼び出す際にジェネリクス引数を渡して、デフォルトの推論をオーバーライドすることで、簡潔に指定できます。
const foo = ref<string | number>('foo') // foo の型: Ref<string | number>
foo.value = 123 // ok!
2
3
ジェネリックの型が不明な場合は、ref
を Ref<T>
にキャストすることをおすすめします:
function useState<State extends string>(initial: State) {
const state = ref(initial) as Ref<State> // state.value -> State extends string
return state
}
2
3
4
# unref
引数が ref
の場合はその内部の値を、そうでない場合は引数そのものを返します。これは、val = isRef(val) ? val.value : val
のシュガー(簡易)関数です。
function useFoo(x: number | Ref<number>) {
const unwrapped = unref(x) // unwrapped は number であることが保証されます
}
2
3
# toRef
ソースとなるリアクティブオブジェクトのプロパティに対する ref
を作成するために使用できます。この ref は、ソースのプロパティへのリアクティブな接続を維持したまま、引き渡すことができます。
const state = reactive({
foo: 1,
bar: 2
})
const fooRef = toRef(state, 'foo')
fooRef.value++
console.log(state.foo) // 2
state.foo++
console.log(fooRef.value) // 3
2
3
4
5
6
7
8
9
10
11
12
toRef
は、prop の ref を composition 関数に渡したいときに便利です:
export default {
setup(props) {
useSomeFeature(toRef(props, 'foo'))
}
}
2
3
4
5
toRef
は、ソースとなるプロパティが現在存在しない場合でも、使用可能な ref を返します。これは、toRefs` で取得されない省略可能な props を扱うときに特に便利です。
# toRefs
リアクティブなオブジェクトをプレーンオブジェクトに変換します。変換後のオブジェクトの各プロパティは、元のオブジェクトの対応するプロパティを指す ref
となります。
const state = reactive({
foo: 1,
bar: 2
})
const stateAsRefs = toRefs(state)
/*
stateAsRefs の型:
{
foo: Ref<number>,
bar: Ref<number>
}
*/
// ref と元のプロパティは「リンク」している
state.foo++
console.log(stateAsRefs.foo.value) // 2
stateAsRefs.foo.value++
console.log(state.foo) // 3
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
toRefs
は、composition 関数からリアクティブなオブジェクトを返すときに便利で、利用する側のコンポーネントはリアクティビティを失うことなく、返されたオブジェクトを分割代入できます:
function useFeatureX() {
const state = reactive({
foo: 1,
bar: 2
})
// 状態で動作するロジック
// 返すときに ref に変換する
return toRefs(state)
}
export default {
setup() {
// リアクティビティを失うことなく分割代入できる
const { foo, bar } = useFeatureX()
return {
foo,
bar
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
toRefs
はソースオブジェクトに含まれるプロパティの ref を生成するだけです。特定のプロパティのリファレンスを作成するには、代わりに toRef
を使用してください。
# isRef
値が ref オブジェクトであるかどうかをチェックします。
# customRef
依存関係の追跡と更新のトリガを明示的に制御する、カスタマイズされた ref を作成します。track
と trigger
関数を引数として受け取り、get
と set
を持つオブジェクトを返すファクトリ関数が必要です。
v-model
でデバウンスを実装するためにカスタム ref を使用した例:<input v-model="text" />
1function useDebouncedRef(value, delay = 200) { let timeout return customRef((track, trigger) => { return { get() { track() return value }, set(newValue) { clearTimeout(timeout) timeout = setTimeout(() => { value = newValue trigger() }, delay) } } }) } export default { setup() { return { text: useDebouncedRef('hello') } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
型:
function customRef<T>(factory: CustomRefFactory<T>): Ref<T>
type CustomRefFactory<T> = (
track: () => void,
trigger: () => void
) => {
get: () => T
set: (value: T) => void
}
2
3
4
5
6
7
8
9
# shallowRef
自分自身の .value
の変更を追跡するが、その値をリアクティブにはしない ref を作成します。
const foo = shallowRef({})
// ref の値を変更するのはリアクティブ
foo.value = {}
// ただし、値は変換されない
isReactive(foo.value) // false
2
3
4
5
# triggerRef
shallowRef
に関連付けられている副作用を手動で実行します。
const shallow = shallowRef({
greet: 'Hello, world'
})
// 初回実行時に "Hello, world" と出力される
watchEffect(() => {
console.log(shallow.value.greet)
})
// shallowRef なので、これでは副作用をトリガしません
shallow.value.greet = 'Hello, universe'
// "Hello, universe" と出力
triggerRef(shallow)
2
3
4
5
6
7
8
9
10
11
12
13
14