vue3组合式api的函数系列一

1、响应式核心

1)、 ref(值)

1)、功能:接受值,返回一个响应式的、可更改的 ref 对象,ref对象只有一个属性:value。value属性保存着接受的值。

2)、使用ref对象:模板上不需要写 .value 属性(会自动解构),在js中,使用 .value 来完成数据的读写

3)、ref可以接收基本类型和引用类型

  • ref可以接收基本类型。

  • ref也可以接收引用类型:如果将一个对象传给 ref函数,那么这个对象将通过 reactive() 转为具有深层次响应式的对象。

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

示例




    
    
    
    Document

    
    
               

msg:{{msg}}

           

以后创建 非 对象类型的数据 使用 ref, 创建对象类型的数据建议使用 reactive

2)、 reactive(对象)

1)、功能: 接受一个对象,返回一个对象的响应式代理(proxy)。返回的对象以及其中嵌套的对象都会通过 ES Proxy 包裹,因此不等于源对象,建议只使用响应式代理,避免使用原始对象。

响应式转换是“深层”的:它会影响到所有嵌套的属性。一个响应式对象也将深层地解包任何 ref 属性,同时保持响应性。【解释一下”解包“,也就是说不用 .value。或者说读取ref属性时,自动会把.value属性的值拿到。】

2)、注意点:当访问到某个响应式数组或 Map 这样的原生集合类型中的 ref 元素时,不会执行 ref 的解包【还得使用.value】。

创建一个响应式对象:

const obj = reactive({ count: 0 })
obj.count++
2.1)、reactive的基本使用,对象使用reactive

reactive示例:




    
    
    
    Document

    
    
               

person.name:{{person.name}}

       

person.sex:{{person.sex}}

       

person.age:{{person.age}}

               

person.wife.age:{{person.wife.age}}

               
               

book.name:{{book.name}}

       

book.price:{{book.price}}

               

book.author.age:{{book.author.age}}

               
               

msg:{{msg}}

           

2.2)把ref对象赋给reactive,会自动解包




    
    
    
    Document

    
    
             

countRef:{{countRef}}

       

personReactive.count:{{personReactive.count}}

           

2.3)、注意:ref类型的数组元素不会解构。

当访问到某个响应式数组或 Map 这样的原生集合类型中的 ref 元素时,不会执行 ref 的解包(模板上也不会解包):

const books = reactive([ref('Vue 3 Guide'),ref(5)])//给reactive传入的是数组。不会解包
// 这里需要 .value
console.log(books[0].value)//'Vue 3 Guide'
console.log(books[1].value)//5
​
const map = reactive(new Map([['count', ref(0)]]))//给reactive传入的是Map。不会解包
// 这里需要 .value
console.log(map.get('count').value)

示例:




    
    
    
    Document

    
    
             
               
  •                                

    {{item.value}}

               
  •        
           

reactive 和 ref的选用:

对象用reactive,其它用ref

3)、 readonly()

1)、功能:接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理。

2)、只读代理是深层的:对任何嵌套属性的访问都将是只读的。它的 ref 解包行为与 reactive() 相同,但解包得到的值是只读的。

const original = reactive({ count: 0 })
​
const copy = readonly(original)
​
watchEffect(() => {
  // 用来做响应性追踪
  console.log(copy.count)
})
​
// 更改源属性会触发其依赖的侦听器
original.count++
​
// 更改该只读副本将会失败,并会得到一个警告
copy.count++ // warning

示例:




    
    
    
    Document

    
    
             

bookReadonly.name:{{bookReadonly.name}}

       

bookReadonly.author.name:{{bookReadonly.author.name}}

           

原生中 const 只能让对象本身只读,不能让对象的属性(包括嵌套属性)只读。

但是,readonly可以让对象的属性(包括嵌套属性)只读

既就是:

const:限制的是:地址(变量对应内存的内容)是只读的。

readonly:限制的是:值(变量引用的内存区域)是只读的

4)、 computed ()
  • 功能:computed是计算属性。和选项式api中的计算属性实现的功能一样。

  • 参数:

    • 可以接受一个 getter 函数,返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。

    • 也可以接受一个带有 getset 函数的对象来创建一个可写的 ref 对象。

4.1)、创建一个只读的计算属性 ref:
const count = ref(1)
const plusOne = computed(() => count.value + 1)
​
console.log(plusOne.value) // 2
​
plusOne.value++ // 错误
4.2)、创建一个可写的计算属性 ref:
const count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: (val) => {
    count.value = val - 1
  }
})

plusOne.value = 1
console.log(count.value) // 0

示例:




    
    
    
    Document

    
    
                     

count:{{count}}

       

doubleCount:{{doubleCount}}

               
        ​        

age:{{age}}

       

wifeAge:{{wifeAge}}

                      ​    

5)、 watch()
watch(第一个参数,第二个参数,第三个参数)

功能:侦听数据的变化,和选项式api中的watch实现的功能一样,组合式api中watch功能更加强大,灵活。默认是懒侦听的,即仅在侦听源发生变化时才执行回调函数。

参数:

  • 第一个参数:侦听器的,可以是以下几种:

    • 一个函数(返回一个值的函数)

    • 一个 ref

    • 一个reactive

    • ...或是由以上类型的值组成的数组

  • 第二个参数:在(第一个参数的值)发生变化时要调用的回调函数。这个回调函数接受三个参数:新值、旧值,以及一个用于注册副作用清理(函数)的回调函数。该回调函数(副作用清理的函数)会在副作用下一次重新执行前调用,可以用来清除无效的副作用,例如:等待中的异步请求。

当侦听多个来源时,回调函数接受两个数组,分别对应来源数组中的新值和旧值。

  • 第三个参数:可选的, 是一个对象,支持以下这些选项:

    • immediate:在侦听器创建时立即触发回调。第一次调用时旧值是 undefined

    • deep:如果源是对象,侦听的源(是ref),强制深度遍历,以便在深层级变更时触发回调。参考深层侦听器。

返回值: 是个函数,该函数可以停止侦听。

与 watchEffect() 相比,watch() 使我们可以:

  • 懒执行副作用;

  • 更加明确是应该由哪个状态触发侦听器重新执行;

  • 可以访问所侦听状态的前一个值和当前值。

  • 示例

    侦听一个 ref(侦听ref 不用写value):

    const count = ref(0)
    watch(count, (count, prevCount) => {
      /* ... */
    })

    侦听一个 getter 函数:

  const state = reactive({ count: 0 })
watch(
    () => state.count,
    (count, prevCount) => {
      /* ... */
    }
  )

当侦听多个来源时,回调函数接受两个数组,分别对应来源数组中的新值和旧值:

  watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
    /* ... */
  })

当使用 getter 函数作为源时,回调只在此函数的返回值变化时才会触发。如果你想让回调在深层级变更时也能触发,你需要使用 { deep: true } 强制侦听器进入深层级模式。在深层级模式时,如果回调函数由于深层级的变更而被触发,那么新值和旧值将是同一个对象。

  const state = reactive({ count: 0 })
  watch(
    () => state,
    (newValue, oldValue) => {
      // newValue === oldValue
    },
    { deep: true }
  )

当直接侦听一个响应式对象时,侦听器会自动启用深层模式:

  const state = reactive({ count: 0 })
  watch(state, () => {
    /* 深层级变更状态所触发的回调 */
  })

示例:




    
    
    
    Document

    
    
                     

age:{{age}}

       

wifeAge:{{wifeAge}}

               
​         ​        

person.name:{{person.name}}

       

person.wife.name:{{person.wife.name}}

               
  ​                              

count:{{count}}

                ​        

inc:{{inc}}

               
​                

a:{{objReactive.a}}

       

b.b1:{{objReactive.b.b1}}

                               
                                         
                   

6)、 watchEffect()

watchEffect

function watchEffect(
  effect: (onCleanup: OnCleanup) => void,
  options?: WatchEffectOptions
): StopHandle

  • 功能: watchEffect也是监听数据,但是它会立即运行一个函数,而不是懒侦听。watchEffect侦听(依赖)的数据:watchEffect里使用了哪个数据,哪个数据就是watchEffect的依赖。watchEffect是深度侦听的。

  • 参数:

    • 第一个参数:要运行的副作用函数。这个副作用函数的参数也是一个函数,注册副作用清理的回调函数。该回调函数会在副作用下一次重新执行前调用,可以用来清除无效的副作用,例如:等待中的异步请求。(和watch的第二个参数中回调函数的第三参数一样)。

  • 第二个参数:可选的选项,可以用来调整副作用的刷新时机或调试副作用的依赖。因为,侦听默认是在vue组件更新前调用,如果你希望组件更新后调用,可以把第二个参数传入:{ flush: 'post' }

  • 返回值:用来停止该副作用的函数。

const count = ref(0)
​
watchEffect(() => console.log(count.value))
// -> 输出 0
​
count.value++
// -> 输出 1

6.1)、基本使用(副作用)



    
    
    
    Document

    
    
             

age:{{age}}

       

isAdult:{{isAdult}}

                       

count:{{count}}

       

isLimit:{{isLimit}}

       

limitChina:{{limitChina}}

           
​ ​ ​

6.2)、副作用清除:

下面的示例,有点像防抖。




    
    
    
    Document

    
    
             

count:{{count}}

       

isLimit:{{isLimit}}

           

6.3)、停止侦听器:
 const stop = watchEffect(() => {
     console.log(count.value)
 })
 // 当不再需要此侦听器时:
 const stopWatch = () => {
     stop()
 }

示例:




  
  
  
  watchEffect


  
       

p01的内容:{{msg}}

    ​    
         
  • 请求第一条数据
  •      
  • 请求第二条数据
  •      
  • 请求第三条数据
  •    
 

watchEffect没有具体监听哪一个值的变化,只要内部有某一个状态发生改变就会执行

你可能感兴趣的:(vue.js,前端,javascript)