Vue3-组合式API学习之响应式系统API

学习来源

响应系统API

1.reactive

接收一个普通对象然后返回该普通对象的响应式代理。等同于2.x的Vue.observable();

实例:
import {reactive} from 'vue';

setup(){
	const state = reactive({
		count : 0
	})
	return state
}

reactive响应式转换是’深层的’,会影响对象内部所有嵌套的属性。基于ES2015的Proxy实现,返回的代理对象不等于原始对象。建议仅使用代理对象而避免依赖原始对象。

2.ref

接收一个参数值并返回一个响应式且可改变的ref对象。ref对象拥有一个指向内部值的单一属性.value

const count = ref(0)
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

如果传入ref的值是一个对象,将调用reactive方法进行深层响应转换。

2.1 模板中访问

当ref作为渲染上下文的属性返回(即在setup()返回的对象中)并在模板中使用时,它会自动解构,无需在模板内额外书写.value。



如果传入ref的值是一个对象,将调用reactive方法进行深层响应转换。例如



2.2 类型标注

有时我们可能需要为ref做一个较为复杂的类型标注。我们可以通过在调用ref时传递泛型参数来覆盖默认推导:



3.computed

3.1 传入一个getter函数,返回一个默认不可手动修改的ref对象



3.2 传入一个拥有get和set函数的对象,创建一个可手动修改的计算状态



因为computed中有set方法,所以在计算时会直接调用set方法设置值,当我们plusOne.value赋值为2时,计算时set中val参数的值为2,计算结果为1;

4.readonly

传入一个对象(响应式或普通)或ref,返回一个原始对象的只读代理。一个只读的代理是“深层的”,对象内部任何嵌套的属性也都是只读的。



5.watchEffect

立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数。当watchEffect在组件的setup()函数或生命周期钩子被调用时,侦听器会被链接到该组件的生命周期,并在卸载时自动停止。



5.1 清除副作用

有时副作用函数会执行一些异步的副作用,这些相应需要在其失效时清除(即完成之前状态已经改变了)。所以侦听副作用传入的函数可以接受一个onInvalidate函数作入参,用来注册清理失效时的回调,当以下情况发生时,这个失效回调会被触发:

  • 副作用即将重新执行时
  • 侦听器被停止(如果在setup()或生命周期钩子函数中使用了watchEffect,则在卸载组件时)
watchEffect((onInvalidate) => {
  const token = performAsyncOperation(id.value)
  onInvalidate(() => {
    // id 改变时 或 停止侦听时
    // 取消之前的异步操作
    token.cancel()
  })
})

我们之所以是通过传入一个函数去注册失效回调,而不是从回调返回它,是因为返回值对于异步错误处理很重要。在执行数据请求时,副作用函数往往是一个异步函数,我们知道异步函数都会隐式地返回一个Promise,但是清理函数必须要在Promise被resolve之前被注册。另外,Vue依赖这个返回的Promise来自动处理Promise链上的潜在错误。

5.2 副作用刷新时机

Vue的响应式系统会缓存副作用函数,并异步地刷新他们,这样可以避免在同一个tick中多个状态改变导致的不必要的重复调用。在核心的具体实现中,组件的更新函数也是一个被侦听的副作用。当一个用户定义的副作用函数进入队列时,会在所有的组件更新后执行:

eg:watchEffect监听时机



在这个例子中:

  • count会在初始运行时同步打印出来
  • 更改count时,将在组件更新后执行副作用

请注意,初始化运行是在组件mounted之前执行的,因此,如果你希望在编写副作用函数时访问DOM(或模板ref),请在onMounted钩子中进行:

onMounted(() => {
  watchEffect(() => {
    // 在这里可以访问到 DOM 或者 template refs
  })
})

如果副作用需要同步或在组件更新之前重新运行,我们可以传递一个拥有flush属性的对象作为选项(默认为’post’):

// 同步运行
watchEffect(
  () => {
    /* ... */
  },
  {
    flush: 'sync',
  }
)

// 组件更新前执行
watchEffect(
  () => {
    /* ... */
  },
  {
    flush: 'pre',
  }
)

5.3 侦听器调试

onTrack 和 onTrigger 选项可用于调试一个侦听器的行为。

  • 当一个reactive对象属性或一个ref作为依赖被追踪时,将调用onTrack
  • 依赖项变更导致副作用被触发时,将调用onTrigger
  • onTrack和onTrigger仅在开发模式下生效

6.watch

watch需要侦听特定的数据源,并在回调函数中执行副作用。默认情况是懒执行的,也就是说仅在侦听的源变更时才执行回调。

对比watchEffect,watch允许我们:

  • 懒执行副作用
  • 更明确哪些状态的改变会触发侦听器重新运行副作用
  • 访问侦听状态变化前后的值

6.1 侦听单个数据源

侦听器的数据源可以是一个拥有返回值的getter函数,也可以是ref



6.2 侦听多个数据源

watcher 也可以使用数组来同时侦听多个源:



watch侦听数据,格式为watch(第一个参数为被检测的数据,第二个参数为数据发生变化后执行的回调函数)。

6.3 与watchEffect共享的行为

watch 和 watchEffect在停止侦听,清除副作用(相应地onInvalidate会作为回调的第三个参数传入),副作用刷新时间和侦听器调试等方面行为一致。

你可能感兴趣的:(Vue,vue)