vue3.0(五) reactive全家桶

vue3.0(五) reactive全家桶

码农世界 2024-05-15 前端 65 次浏览 0个评论

文章目录

  • 1 reactive
    • 1.1 reactive的应用
    • 1.2 reactive的特点
    • 1.3 reactive的注意
    • 1.4 reactive的局限性
    • 2 toRefs
    • 3 isReactive
    • 4 shallowReactive
    • 5 readonly
      • 5.1 readonly 详细信息
      • 5.2 readonly函数创建一个只读的响应式对象
      • 5.3 如何修改嵌套在只读响应式对象中的对象?
      • 6 isReadonly
      • 7 shallowReadonly
      • 8 isProxy
      • 总结

        1 reactive

        1.1 reactive的应用

        reactive是另一种声明响应式状态的方式,与将内部值包装在特殊对象中的 ref 不同,reactive() 将使对象本身具有响应性:

        import { reactive } from 'vue'
        // 声明state
        const state = reactive({ count: 0 })
        // js中的应用和ref不同不需要value
         console.log(state)
        // html模版中应用
         
        {{ state.count }}

        响应式对象是 JavaScript 代理,其行为就和普通对象一样。不同的是,Vue 能够拦截对响应式对象所有属性的访问和修改,以便进行依赖追踪和触发更新。

        reactive() 将深层地转换对象:当访问嵌套对象时,它们也会被 reactive() 包装。当 ref 的值是一个对象时,ref() 也会在内部调用它。与浅层 ref 类似,这里也有一个 shallowReactive() API 可以选择退出深层响应性。

        1.2 reactive的特点

        • 实现引用类型数据的响应式,如数组、对象等
        • ref去创建引用类型的响应式,其实内部也是调用了reactive
        • reactive创建的响应式对象,调用时不用.value

          在Vue3中,reactive函数是用于创建响应式对象的函数。它接收一个普通对象作为参数,返回一个代理对象。这个代理对象可以拦截对象的get和set操作,并在其中实现响应式的逻辑。当我们读取代理对象的属性时,会触发依赖收集;当我们修改代理对象的属性时,会触发相应的依赖更新。在调用reactive函数时,Vue3会使用Proxy对象对传入的对象进行代理,从而实现响应式的特性。

          1.3 reactive的注意

          • reactive() 返回的是一个原始对象的 Proxy,它和原始对象是不相等的:
            const obj = {}
            const proxy = reactive(obj)
            // 代理对象和原始对象不是全等的
            console.log(proxy === obj) // false
            
          • 为保证访问代理的一致性,对同一个原始对象调用 reactive() 会总是返回同样的代理对象,而对一个已存在的代理对象调用 reactive() 会返回其本身:
            const obj = {}
            const proxy = reactive(obj)
            // 在同一个对象上调用 reactive() 会返回相同的代理
            console.log(proxy === reactive(obj)) // true
            // 在一个代理上调用 reactive() 会返回它自己
            console.log(reactive(proxy) === proxy) // true
            

            1.4 reactive的局限性

            1. 有限的值类型:它只能用于对象类型 (对象、数组和如 Map、Set 这样的集合类型)。它不能持有如 string、number 或 boolean 这样的原始类型。
            2. 不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地“替换”响应式对象,因为这样的话与第一个引用的响应性连接将丢失:
            
            
            
            1. 对解构操作不友好:当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:
              
              
              
              

            2 toRefs

            1. 将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。
               const state = reactive({
                 foo: 1,
                  bar: 2
                })
                const stateAsRefs = toRefs(state)
                /*
                stateAsRefs 的类型:{
                  foo: Ref,
                  bar: Ref
                }
                */
                // 这个 ref 和源属性已经“链接上了”
                console.log(stateAsRefs) // {foo: ObjectRefImpl, bar: ObjectRefImpl}
                state.foo++
                console.log(stateAsRefs.foo.value)// 2
                stateAsRefs.foo.value++
                console.log(state.foo)// 3
              
              1. 组件可以解构/展开返回的对象而不会失去响应性:
              
              
              
              

            toRefs 在调用时只会为源对象上可以枚举的属性创建 ref。如果要为可能还不存在的属性创建 ref,请改用 toRef。

            3 isReactive

            检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。

            const state = readonly(reactive({
              count: 1,
              name: 'Tom'
            }))
            console.log(state.count)// 1
            console.log(state.name)// Tom
            console.log(isReactive(state)) // true
            

            4 shallowReactive

            1. reactive() 的浅层作用形式。
            2. 和 reactive() 不同,这里没有深层级的转换:一个浅层响应式对象里只有根级别的属性是响应式的。属性的值会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了
            
            
            

            5 readonly

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

            5.1 readonly 详细信息

            • 只读代理是深层的:对任何嵌套属性的访问都将是只读的。它的 ref 解包行为与 reactive() 相同,但解包得到的值是只读的。
            • 要避免深层级的转换行为,请使用 shallowReadonly() 作替代。

              5.2 readonly函数创建一个只读的响应式对象

                const state = readonly(reactive({
                    count: 1,
                    name: 'Tom'
                  }))
                  console.log(state.count)// 1
                  console.log(state.name)// Tom
              

              5.3 如何修改嵌套在只读响应式对象中的对象?

              使用readOnly函数创建的只读对象,内部的属性无法修改

                 const state = readonly(reactive({
                    count: 1,
                    name: 'Tom'
                  }))
                  console.log(state.count)// 1
                  state.name = 'diXi' // 输出警告信息,不会触发依赖更新
                  console.log(state.name)// Tom
              

              注意:使用 readonly 函数创建的只读响应式对象是深层只读的。也就是说,当我们尝试修改嵌套在只读响应式对象中的对象时,会输出警告信息,不会触发相应的依赖更新。

              6 isReadonly

              • 检查传入的值是否为只读对象。只读对象的属性可以更改,但他们不能通过传入的对象直接赋值。
              • 通过 readonly() 和 shallowReadonly() 创建的代理都是只读的,因为他们是没有 set 函数的 computed() ref。
                const state = readonly(reactive({
                   count: 1,
                   name: 'Tom'
                 }))
                 console.log(state.count)// 1
                 console.log(state.name)// Tom
                 console.log(isReadonly(state)) // true
                

                7 shallowReadonly

                • readonly() 的浅层作用形式
                • 和 readonly() 不同,这里没有深层级的转换:只有根层级的属性变为了只读。属性的值都会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。
                      const state1 = readonly(reactive({
                        foo: 1,
                        nested: {
                          bar: 2
                        }
                      }))
                      const state = shallowReadonly(reactive({
                        foo: 1,
                        nested: {
                          bar: 2
                        }
                      }))
                      console.log(state.nested.bar++)
                      // console.log(state1.nested.bar++) // 报错 Cannot assign to 'bar' because it is a read-only property
                      // console.log(state.foo++) // 报错 Cannot assign to 'bar' because it is a read-only property
                      // console.log(state1.foo++) // 报错 Cannot assign to 'bar' because it is a read-only property
                      // ...但可以更改下层嵌套对象
                      isReadonly(state.nested) // false
                      
                  

                  8 isProxy

                  检查一个对象是否是由 reactive()、readonly()、shallowReactive() 或 shallowReadonly() 创建的代理。

                     const state = readonly(reactive({
                        count: 1,
                        name: 'Tom'
                      }))
                   console.log(state.count)// 1
                   console.log(state.name)// Tom
                   console.log(isProxy(state)) // true
                  

                  总结

                  Vue3中用于创建响应式对象的三个函数:

                  reactive、readonly和shallowReactive。

                  reactive函数用于创建深层响应式对象,

                  shallowReactive函数用于创建浅层响应式对象,

                  readonly函数用于创建深层只读响应式对象,

                  shallowReadonly函数用于创建浅层只读响应式对象。

                  这些函数可以帮助我们快速创建响应式数据,实现数据的自动更新。

                  isProxy,isReadonly,isReactive判断是否是相应是对象

                  isProxy 检查一个对象是否是由 reactive()、readonly()、shallowReactive() 或 shallowReadonly() 创建的代理。

                  isReadonly 检查传入的值是否为 readonly() 和 shallowReadonly() 创建的只读对象。

                  isReactive 检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。

转载请注明来自码农世界,本文标题:《vue3.0(五) reactive全家桶》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,65人围观)参与讨论

还没有评论,来说两句吧...

Top