#### 一、Vue.js 响应式系统
1. **ref() 和 reactive()**
- **ref()**:用于将普通值包装成响应式对象。返回一个包含 `.value` 属性的对象,通过 `.value` 访问或修改值。
```javascript
import { ref } from 'vue';
let count = ref(0);
console.log(count.value); // 访问值
count.value = 1; // 修改值
```
- **reactive()**:用于将对象转换为响应式对象。返回一个代理对象(Proxy),直接操作对象属性即可。
```javascript
import { reactive } from 'vue';
let state = reactive({ count: 0 });
state.count++; // 修改值
```
2. **reactive() 的局限性**
- **只能用于对象类型**:不能用于原始类型(如 `string`、`number`)。
- **不能替换整个对象**:替换对象会丢失响应式连接。
```javascript
let state = reactive({ count: 0 });
state = reactive({ count: 1 }); // 响应式连接丢失
```
- **解构操作不友好**:解构会丢失响应性。
```javascript
const state = reactive({ count: 0 });
let { count } = state; // count 与 state.count 断开连接
```
3. **ref 解包**
- **作为 reactive 对象的属性**:自动解包。
```javascript
const count = ref(0);
const state = reactive({ count });
console.log(state.count); // 0
```
- **数组和集合中的 ref**:不会自动解包,需手动访问 `.value`。
```javascript
const books = reactive([ref('Vue 3 Guide')]);
console.log(books[0].value); // 访问值
```
#### 二、计算属性
1.
- 使用 `computed()` 创建计算属性,返回一个响应式 ref。
```javascript
import { reactive, computed } from 'vue';
const author = reactive({
name: 'John Doe',
books: ['Vue 2 Guide', 'Vue 3 Guide']
});
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No';
});
```
2. **计算属性缓存 vs 方法**
- **计算属性缓存**:只有依赖变化时才重新计算,性能更优。
- **方法**:每次调用都会重新执行,无缓存。
```javascript
// 计算属性
const now = computed(() => Date.now()); // 不会更新,因为无响应式依赖
// 方法
function calculateNow() {
return Date.now();
}
```
3. **最佳实践**
- **Getter 不应有副作用**:计算属性的 getter 只负责计算和返回值,不应修改状态或执行异步操作。
- **避免直接修改计算属性值**:计算属性是派生状态,应通过更新依赖的源状态来触发新计算。
#### 三、模板中的响应式状态
1. **ref 和 reactive 的使用**
- **ref**:在模板中自动解包,无需 `.value`。
```vue
<template>
<div>{{ count }}</div>
</template>
<script setup>
import { ref } from 'vue';
let count = ref(0);
</script>
```
- **reactive**:直接使用对象属性。
```vue
<template>
<div>{{ state.count }}</div>
</template>
<script setup>
import { reactive } from 'vue';
let state = reactive({ count: 0 });
</script>
```