Vue 響應式狀態
# Vue 響應式狀態觀念
Vue 的「響應式」是指:
> 當狀態資料改變時,Vue 會自動追蹤依賴這些資料的畫面,並重新更新畫面。
例如:
```js
count.value++
```
如果畫面上有使用 `count`,Vue 會自動重新渲染相關內容,不需要手動操作 DOM。
---
## 一、常見的響應式 API
### 1. `ref()`
適合用來建立單一值,例如數字、字串、布林值。
```js
import { ref } from 'vue'
const count = ref(0)
```
在 JavaScript 中需要透過 `.value` 存取:
```js
count.value++
console.log(count.value)
```
但在 Vue Template 中會自動解包,不需要 `.value`:
```html
<p>{{ count }}</p>
```
---
### 2. `reactive()`
適合建立物件或陣列的響應式狀態。
```js
import { reactive } from 'vue'
const user = reactive({
name: '小明',
age: 20
})
user.name = '小華'
user.age++
```
Template 中可以直接使用:
```html
<p>{{ user.name }}</p>
<p>{{ user.age }}</p>
```
注意:`reactive()` 只能用於物件類型,且不建議直接替換整個物件:
```js
// 不建議
user = { name: '小華', age: 21 }
```
若需要替換整個值,使用 `ref()` 會比較合適。
---
## 二、響應式狀態的基本操作流程
通常可以分成以下幾個步驟:
1. **建立狀態**
```js
const count = ref(0)
```
2. **在 Template 中顯示狀態**
```html
<p>{{ count }}</p>
```
3. **透過事件修改狀態**
```html
<button @click="count++">增加</button>
```
4. **Vue 自動更新畫面**
使用者點擊按鈕後,狀態變更,Vue 會重新計算相關畫面內容。
---
## 三、`computed` 與 `watch`
### `computed`
適合根據其他狀態計算出衍生資料,並具有快取效果。
```js
import { ref, computed } from 'vue'
const price = ref(100)
const quantity = ref(2)
const total = computed(() => price.value * quantity.value)
```
Template:
```html
<p>總價:{{ total }}</p>
```
只有當 `price` 或 `quantity` 改變時,`total` 才會重新計算。
---
### `watch`
適合在狀態變更時執行額外動作,例如呼叫 API、儲存資料或記錄訊息。
```js
import { ref, watch } from 'vue'
const keyword = ref('')
watch(keyword, (newValue, oldValue) => {
console.log('關鍵字變更為:', newValue)
})
```
---
# 範例一:計數器
這是一個使用 `ref()` 的簡單互動範例。
```vue
<script setup>
import { ref, computed } from 'vue'
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increase() {
count.value++
}
function decrease() {
count.value--
}
function reset() {
count.value = 0
}
</script>
<template>
<div>
<h2>計數器</h2>
<p>目前數值:{{ count }}</p>
<p>兩倍數值:{{ doubleCount }}</p>
<button @click="decrease">-1</button>
<button @click="increase">+1</button>
<button @click="reset">重設</button>
</div>
</template>
```
## 運作流程
1. `count` 初始值為 `0`
2. 使用者點擊按鈕
3. `count.value` 被修改
4. Vue 偵測到狀態變化
5. `count` 和 `doubleCount` 的畫面自動更新
在 Template 中:
```html
{{ count }}
```
不需要寫成:
```html
{{ count.value }}
```
---
# 範例二:待辦事項清單
這個範例示範 `ref()`、陣列操作、輸入綁定和事件處理。
```vue
<script setup>
import { ref, computed } from 'vue'
const newTodo = ref('')
const todos = ref([
{ id: 1, text: '學習 Vue', done: false },
{ id: 2, text: '完成練習', done: true }
])
function addTodo() {
const text = newTodo.value.trim()
if (!text) return
todos.value.push({
id: Date.now(),
text,
done: false
})
newTodo.value = ''
}
function removeTodo(id) {
todos.value = todos.value.filter(todo => todo.id !== id)
}
const remainingCount = computed(() => {
return todos.value.filter(todo => !todo.done).length
})
</script>
<template>
<div>
<h2>待辦事項</h2>
<input
v-model="newTodo"
placeholder="輸入待辦事項"
@keyup.enter="addTodo"
/>
<button @click="addTodo">新增</button>
<p>尚未完成:{{ remainingCount }} 件</p>
<ul>
<li v-for="todo in todos" :key="todo.id">
<label>
<input type="checkbox" v-model="todo.done" />
<span :style="{ textDecoration: todo.done ? 'line-through' : 'none' }">
{{ todo.text }}
</span>
</label>
<button @click="removeTodo(todo.id)">刪除</button>
</li>
</ul>
</div>
</template>
```
## 範例中的響應式操作
### 雙向綁定
```html
<input v-model="newTodo" />
```
`v-model` 會同步:
- 輸入框的內容
- `newTodo` 的值
### 新增資料
```js
todos.value.push({
id: Date.now(),
text,
done: false
})
```
新增項目後,Vue 會自動更新 `v-for` 產生的清單。
### 修改物件屬性
```html
<input type="checkbox" v-model="todo.done" />
```
勾選核取方塊時,`todo.done` 會自動變更,文字樣式也會隨之更新。
### 刪除資料
```js
todos.value = todos.value.filter(todo => todo.id !== id)
```
重新指定陣列後,Vue 會更新清單內容。
---
## 四、常見注意事項
### 在 JavaScript 中別忘記 `.value`
```js
const name = ref('Vue')
// 正確
name.value = 'Vue 3'
// 錯誤
name = 'Vue 3'
```
### Template 中不需要 `.value`
```html
<p>{{ name }}</p>
```
### 使用 `v-for` 時提供 `key`
```html
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
```
`key` 能協助 Vue 正確辨識每個項目,提升更新效率。
### 狀態應集中管理
小型元件可以直接使用 `ref()` 或 `reactive()`。若多個元件需要共用狀態,可以考慮:
- 父子元件的 `props` 與 `emit`
- Pinia
- Composable,例如 `useCounter()`
總結來說,Vue 響應式狀態的核心流程是:
> 建立狀態 → 在畫面中使用 → 透過事件修改 → Vue 自動更新畫面。
相關學習地圖、教學課程
F2E 網站前端工程