[TOC]

computed 计算

与 Options API 基本一致

const count = ref(1);

// 返回 get 的只需要用一个回调函数
const myCount = computed(() => count.value * 2);

// getter / setter, 使用一个带有 get 和 set 方法的对象
const yourCount = computed({
    get(){
      return count.value * 2;
  },
  set(val){
      count.value = val + 1;
  }
});

watchEffect

根据响应式状态自动就用和重新应用副作用。(和 React Hooks 的 useEffect 相似)
会立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数

停止侦听

返回一个停止侦听的函数,可以显式停止侦听。
而在组件卸载时自动停止侦听

const count = ref(1);
const name = ref('Mr.Lee');

// 第一次运行会先执行一次
watchEffect(() => {
  console.log("effect~");
});

// 响应式追踪依赖
const stop = watchEffect(() => {
  // 输出响应式数据 count,会自动收集其依赖,监控依赖变更
  // 如果依赖进行变更,会再一次执行一次回调函数
  console.log(count.value);
});

name.value = "Ms.Wang"; // 这里不会收集,因为 watchEffect 没用到这个响应式数据

const id = setInterval(() => {
  // 会被 watchEffect 当作依赖收集,并监控变更
  count.value++; 
  if (count.value > 20) {
    stop(); // 手动停止侦听
  }

  if (count.value > 30) clearInterval(id);
}, 100);

onInvalidate 清除副作用

在使用 watchEffect 异步操作时,会产生一些副作用,需要一些清理手段
而清理这些需要在失效时清理,即完成之前状态清理掉
watchEffect 提供侦听副作用的参数 onInvalidate

  • onInvalidate 当副作用失效时回调
  • 当依赖变更执行 watchEffect 时,最先执行这个副作用回调
    当第二执行时,会先执行 onInvalidate 回调,再执行上面的输出 ```vue

<a name="szRhv"></a>
## watchEffect 的 options
<a name="BcDV3"></a>
### 侦听的时机 

- 默认 flush: 'pre' <br />清除副作用 -> 侦听内容 -> onBeforeUpdate
- flush: 'post'<br />onBeforeUpdate -> 清除副作用 -> 侦听内容
<a name="ryvRY"></a>
### 侦听器调试
在开发模式时使用

- onTrack(e) 将在响应式 property 或 ref 作为依赖项被追踪时被调用
- onTrigger(e) { debugger; } 将在依赖项变更导致副作用被触发时被调用
<a name="bn4CH"></a>
# watch
与 Options API 对象配置一样

1. 侦听特定的数据源(watchEffect 是收集依赖式)
2. 副作用在第二参数回调执行,并且是懒执行
3. 可以访问当前改变的值和改变前的值
```javascript
const count = ref(0);
const name = ref('Mr.Lee');

// ref 对象,会自动 unwrap
watch(count, (count, prevCount) => {
    console.log('count:', count, 'prevCount:', prevCount);
});

// 回调函数,ref 对象要手动 unwrap
watch(() => count.value, (count, prevCount) => {
    console.log('count:', count, 'prevCount:', prevCount);
});

// 侦听多个,使用数组
watch([count, name], ([count, prevCount], [name, prevName]) => {
    console.log('count:', count, 'prevCount:', prevCount);
  console.log('name:', name, 'prevName:', prevName);
});

// 尝试检查深度嵌套对象或数组中的 property 变化, 第三个参数 options 对象的 deep 设置为 true
const state = reactive({ 
  id: 1, 
  attributes: { 
    name: "",
  },
}); 

watch(
  () => state,
  (state, prevState) => {
    console.log(
      "deep ",
      state.attributes.name,
      prevState.attributes.name
    );
  },
  { deep: true }
);