• 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没有具体监听哪一个值的变化,只要内部有某一个状态发生改变就会执行

  • 相关阅读:
    react面试题
    pwn学习(2)test_your_nc
    记Halo1.5版本迁移Halo2.10.0版本
    利用frps搭建本地自签名https服务的透传
    如何在IDEA中创建Module、以及怎样在IDEA中删除Module?
    太绝了!这份Python爬虫入门『最强教程』当之无愧
    2024Python二级
    微信小程序
    Vue练习CRUD
    无胁科技-TVD每日漏洞情报-2022-7-31
  • 原文地址:https://blog.csdn.net/jiang7701037/article/details/133284447