http://www.manongjc.com/detail/26-krnsyulausdxmlq.html
接受一個內部值,返回一個響應式的、可更改的 ref 對象,此對象只有一個指向其內部值的 property`.value`。
一般用來定義一個基本類型的響應式數據Undefined、Null、Boolean、Number和String,除此之外也可以用來定義簡單的`Object`響應式數據,當然一般深層的`Object`等復雜數據均是使用`reactive`定義。
**注意**:在`ts`或者`js`中操作數據需要使用`xxx.value`的形式,而模板中不需要添加`.value`
```ts
import { ref } from 'vue'
const count = ref(0)
const str = ref('hello')
const bool = ref(true)
```
#### 為`ref()`標注類型
`ref`會根據初始化時的值推導其類型:
```ts
import { ref } from 'vue'
// 推導出的類型:Ref<number>
const year = ref(2020)
// => TS Error: Type 'string' is not assignable to type 'number'.
year.value = '2020'
```
有時我們可能想為`ref`內的值指定一個更復雜的類型,可以通過使用`Ref`這個類型:
```ts
import { ref } from 'vue'
import type { Ref } from 'vue'
const year: Ref<string | number> = ref('2020')
year.value = 2020 // 成功!
```
或者,在調用`ref()`時傳入一個泛型參數,來覆蓋默認的推導行為:
```ts
// 得到的類型:Ref<string | number>
const year = ref<string | number>('2020')
year.value = 2020 // 成功!
```
如果你指定了一個泛型參數但沒有給出初始值,那么最后得到的就將是一個包含`undefined`的聯合類型:
```ts
// 推導得到的類型:Ref<number | undefined>
const n = ref<number>()
```
#### 訪問模板 ref
為了通過組合式 API 獲得該模板`ref`,我們需要聲明一個同名的`ref`:
```html
<template>
<input ref="input" />
</template>
<script setup>
import { ref, onMounted } from 'vue'
// 聲明一個 ref 來存放該元素的引用
// 必須和模板 ref 同名
const input = ref(null) // 或者標注類型: ref<HTMLInputElement | null>(null)
onMounted(() => {
input.value.focus() // 標注類型后用法:input.value?.focus()
})
</script>
```
**注意**: 只可以在組件掛載后才能訪問`ref`。如果你想在模板中的表達式上訪問`input`,在初次渲染時會是`null`。這是因為在初次渲染前這個元素還壓根不存在呢!
如果你正試圖觀察一個模板`ref`的變化,確保考慮到`ref`的值為`null`的情況:
```ts
watchEffect(() => {
if (input.value) {
input.value.focus()
} else {
// 此時還未掛載,或此元素已經被卸載(例如通過 v-if 控制)
}
})
```