# Vue2 监视属性（Watch）详解文档

## 一、基本概念

监视属性（Watch）是 Vue2 中用于观察和响应数据变化的机制。它允许你在数据变化时执行异步操作或更复杂的逻辑。

## 二、代码示例解析

```html
<div id="app">
    <h2>天气很什么：{{isHot ? '炎热' : '凉爽'}}</h2>
    <button @click="changeWeather">切换天气</button>
</div>

<script>
    const vm = new Vue({
        el: "#app",
        data: {
            isHot: true
        },
        methods: {
            changeWeather() {
                this.isHot = !this.isHot;
            }
        },
        watch: {
            isHot: {
                immediate: true,  // 立即执行handler
                handler(newVal, oldVal) {
                    console.log("天气状态修改", newVal, oldVal);
                }
            }
        }
    });
</script>
```

## 三、核心特性

### 1. 基本语法结构

```javascript
watch: {
    要监视的属性: {
        handler(newValue, oldValue) {
            // 响应变化
        },
        immediate: false,  // 是否立即执行
        deep: false       // 是否深度监视
    }
}
```

### 2. 简写形式（不需要配置项时）

```javascript
watch: {
    isHot(newVal, oldVal) {
        console.log("天气变化", newVal, oldVal);
    }
}
```

### 3. 深度监视（deep watch）

通常监视对象属性。

```javascript
watch: {
    someObject: {
        handler(newVal) {
            console.log("对象内部变化", newVal);
        },
        deep: true  // 深度监视对象内部值变化
    }
}
```

## 四、配置选项说明

| 选项      | 类型     | 默认值 | 说明                         |
| --------- | -------- | ------ | ---------------------------- |
| handler   | Function | 必填   | 数据变化时的回调函数         |
| immediate | Boolean  | false  | 是否立即以当前值执行handler  |
| deep      | Boolean  | false  | 是否深度观察对象内部值的变化 |

## 五、最佳实践

1. **命名规范**：
   - 监视属性通常以 `watch` 开头命名方法（如 `watchIsHotChange`）
   - 或者直接使用被监视的属性名

2. **使用场景**：
   - 数据变化需要执行异步操作时
   - 数据变化需要执行开销较大的操作时
   - 需要观察嵌套数据结构变化时

3. **性能考虑**：
   - 避免在handler中执行复杂同步操作
   - 对于大对象，谨慎使用deep watch

## 六、高级用法

### 1. 监视计算属性

```javascript
computed: {
    weatherDesc() {
        return this.isHot ? "炎热" : "凉爽";
    }
},
watch: {
    weatherDesc(newVal) {
        console.log("天气描述变化:", newVal);
    }
}
```

### 2. 监视路由变化

```javascript
watch: {
    '$route'(to, from) {
        console.log("路由变化", to.path, from.path);
    }
}
```

### 3. 多属性监视

```javascript
watch: {
    // 监视多个属性
    'a.b.c': function(newVal) {
        // 当a.b.c变化时执行
    },
    'x.y': 'someMethod'  // 直接调用methods中的方法
}
```

## 七、与计算属性的比较

| 特性   | 计算属性     | 监视属性     |
| ------ | ------------ | ------------ |
| 目的   | 派生新数据   | 响应数据变化 |
| 缓存   | 有缓存       | 无缓存       |
| 异步   | 不支持       | 支持         |
| 返回值 | 必须返回     | 不需要返回   |
| 复杂度 | 适合简单计算 | 适合复杂逻辑 |

## 八、常见问题

1. **为什么handler没有被调用？**
   - 检查监视的属性名拼写是否正确
   - 确认属性值确实发生了变化（对于对象/数组，可能需要深度监视）

2. **什么时候使用deep watch？**
   - 当需要检测对象内部属性变化时
   - 注意性能影响，必要时可以指定具体路径如 `'obj.prop'`

3. **如何取消监视？**
   - 使用 `vm.$watch()` 返回的取消函数：
     ```javascript
     const unwatch = this.$watch('someProp', handler);
     unwatch();  // 取消监视
     ```
