崇序猿的取经之路 vue3 (一)

297 阅读2分钟

1666611198148.jpg

快乐星球持证驾驶员 冲冲冲!!

一 main.js 区别 vue2 vs vue3

vue3引入的再也不是Vue构造函数了,引入的为一个名为createApp的工厂函数

二 template

vue3中的template不需要根元素

三 setup

  1. setup 中的 this 为 undefined

  2. 组件中所用到的:数据、方法等等,均要配置在setup中。

  3. setup 会在 beforeCreate 之前执行一次。

  4. setup为一个函数,需要 return 。

  5. setup函数中有两种返回值
    5.1 返回一个对象,对象中的属性、方法可以直接在模板中使用。
    5.2 返回一个函数(渲染函数) 但是需要单独引入 h 函数。

  6. setup 可以和2.x的语法一起用 但是不建议一起使用
    6.1 vue2.x的配置(data、methos、···) 可以访问到setup的属性和方法。

      setup最后抛出到this中,methos等方法可以直接 this.xxx 引用   
    

    6.2 但在setup中不能访问到 vue2.0 配置。

      setup 访问不到this  
      console.log(this) // undefined
    

    6.3 如果有重名 setup 优先

  7. setup的参数
    7.1 props:值为响应式对象(proxy),组件外部传递过来。
    7.2 context: 上下文对象

    attrs:类似于vue2的this.$attrs

    slots: 类似于vue2的this.$slots

    emit: 类型与vue2的this.$emit

    export default {
        props: ['hello'],
        emits: ['fn'], // 应该是为了更加的规范  不加这个会有警告
        setup(props: any, context: any) {
            console.log(props) // Proxy {hello: '你好'}
            console.log(context)
            context.emit('fn')
        },
    }

四 ref (Refimpl = 引用对象类型)

     作用:定义一个基本类型的响应式数据
  1. 此ref为一个加工函数,并不是 <buttom ref='but' /> 这个ref,两者互不影响。

  2. ref 本身是一个加工函数,通过 ref 加工后的基本数据类型的数据Refimpl引用对象类型。
    2.1 通过 ref 加工后的 Refimpl 对象后,需要.value来进行获取或者修改。
    2.2 在 template 中是不需要用 .value 来进行获取对应的值,因为 template 可以自动识当前的数据是否为 Refimpl 类型, 是的话会自动并且隐式的加上.value 官方叫 解包

  3. 当 ref 中的数据为 引用数据类型时,ref 会求助3.x中的新方法 — reactive

      reactive 会把当前对象转化为 Proxy 对象     
    
  4. 无论是基本类型还是引用类型,ref 的响应式机制​​始终基于对象封装和 getter/setter

    • ​所有 ref 值都会被包装为一个对象​​,结构为 { value: ... }
    • 通过 RefImpl 类的 get value() 和 set value() 方法实现依赖收集和更新触发
  5. 对基本类型和引用类型的处理差异

    • ​基本类型​​ | 直接存储原始值,通过 getter/setter 监听 .value 的读写操作。

    • ​引用类型​​ | 将值传递给 reactive(),生成 Proxy 代理对象,再存储到 .value 中。

      vue官方文档介绍:如果将对象分配为ref值,则通过 reactive 函数使该对象具有高度的响应式

五 reactive ( proxy对象类型 )

   作用:当数据是复杂对象或数组且不需要替换整个引用时,`reactive` 更直观。
  1. reactive 不支持基本数据类型,会有警告

  2. 在处理对象的时候,vue3使用的Es6的proxy,不再是以前的defineProperty方法。 vue2中响应式原理

    const data ={
        count:10
    }
    object。defineProperty(data,'count',{
        get() {
        }
        set(){
        }
    })

扩展 Reflect

Reflectobject相同,尽管两者之间存在某些微乎其微的的差别  主要是用于框架开发
let of =  Reflect.defineProperty(obj,'c',{
    get(){
    }
    set(){
    }
})
consolg.log(of) // Boolean

vue3中响应式原理

        const obj = {
            name:"张三",
            age:'18'
        }
        const pobj = new proxy(obj,{
             // 当读取 pobj 某属性时会被调用
            get(target,propName){
                return target[propName]
            },
            // 当针对于 pobj 修改或者添加 时会被调用
            set(target,propName,value){
                target[propName] = value
            },
             // 当删除 pobj 某属性时会被调用
            deleteProperty(target,propName){
                return delete target[propName]
            }
        })

差异

        Object.defineProperty 是对 对象属性 的劫持
        Proxy 是对整个对象劫持
        Object.defineProperty 无法监听新增和删除  页面不会响应式更新 
            添加:$set    可以添加
            删除:#delete 可以删除
        Object.defineProperty 无法监听数组部分方法需要重写
        Object.defineProperty 性能不好要对深层对象劫持要一次性递归  性能不好
        Object.defineProperty 直接通过数组的下标修改数据 页面不会响应式

        Proxy 能正确监听数组方法
        Proxy 能正确监听对象新增删除属性
        Proxy 只在 getter 时才进行对象下一层属性的劫持 性能优化
        Proxy 兼容性不好

        Object.definePropertyProxy
        在 getter 时进行添加依赖 `dep.addSub(watcher)` 比如 绑定 view 层,在函数中使用
        在 setter 时触发依赖通知 `dep.notify()` 比如 修改属性

      Object.defineProperty 是对所有对象属性的劫持,如访问obj.o, 所有属性,包括深层的都是响应式,浪费性能    
      Proxy 是对访问到哪个属性,那个属性就是响应式,如访问obj.o,属性o才是响应式, 访问obj.o.b, 
        b才是响应式,访问到那个属性,那个属性才是响应式,不需一次性遍历