Vue3有了解过吗?能说说跟Vue2的区别吗?Vue3性能优化的地方在哪里?静态标记

文章目录

  • 前言、Vue3的核心变化
  • 一、Vue3相比Vue2的优势
  • 二、Vue3.0变化的三大点
        • 1、监测机制的改变:用Proxy替换Object.defineProperty
            • Proxy 是什么
            • `Vue3.0 里为什么要用 Proxy API 替代 defineProperty API?`
            • Proxy 区别于 Object.definedProperty
        • 2、作用域插槽方面
        • 3、对象式的组件声明方式
        • 4、生成 Block tree
        • 5、其它方面的更改
  • 三、非兼容变更
        • 1、模板指令
        • 2、组件
  • 四、Vue3的虚拟dom
        • 1、编译模版的静态标记
        • 2、事件缓存
  • 五、vue3和react fiber的vdom
        • 1、Vue2.x
        • 2、React 16 Fiber
  • 六、Vue3.0 是如何变得更快的?

Vue3有了解过吗?能说说跟Vue2的区别吗?Vue3性能优化的地方在哪里?静态标记_第1张图片

前言、Vue3的核心变化

  • Typescript,
  • Proxy响应式,
  • Composition解决代码反复横跳
  • 虚拟DOM

一、Vue3相比Vue2的优势

  • 1、速度更快 ------- 详细说明见第四大点,Vue3的虚拟DOM

    1、重写了虚拟Dom实现
    2、编译模板的优化
    3、更高效的组件初始化
    4、undate性能提高1.3~25、SSR速度提高了2~3
  • 2、压缩包体积更小
    通过webpack的tree-shaking功能,可以将无用模块“剪辑”,仅打包需要的,这样有两大好处:

    1、对开发人员,不必担忧项目整体体积过大
    
    2、对使用者,打包出来的包体积变小了
    
  • 3、更易维护

    1、compositon Api可与现有的Options API一起使用
    2、VUE3是基于typescript编写的,可以享受到自动的类型定义提示
    
  • 4、更接近原生
    可以自定义渲染 API
    Vue3有了解过吗?能说说跟Vue2的区别吗?Vue3性能优化的地方在哪里?静态标记_第2张图片

  • 5、更易使用

二、Vue3.0变化的三大点

1、监测机制的改变:用Proxy替换Object.defineProperty

关于Proxy,一定程度上会带来的性能上的提升,因为传统的原型链拦截的方法,无法检测对象及数组的一些更新操作,但使用Proxy又带来了浏览器兼容问题。

Proxy 是什么
  • Proxy为 构造函数,用来生成 Proxy实例

    var proxy = new Proxy(target, handler)
    //target 表示所要拦截的目标对象(任何类型的对象,包括原生数组,函数)
    // handler通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为
    
  • 关于handler拦截属性,有如下13种

    • 1、get(对象属性的读取)、
    • 2、set(对象属性的设置)、
    • 3、apply(对函数的调用call、apply操作进行拦截)、
    • 4、has( 用于拦截hasProperty操作,返回一个布尔值)、
    • 5、deleteProperty (拦截delete操作,返回一个布尔值)
    • 6、defineProperty ( 拦截Object.defineProperty操作)
    • 7、getOwnPropertyDescriptor (用于拦截Object.getOwnPropertyDescriptor(),返回一个属性描述对象或者undefined)
    • 8、getPrototypeOf (用于拦截获取对象的原型)
    • 9、isExtensible (拦截Object.isExtensible()操作)
    • 10、ownKeys (用于拦截对象自身属性的读取操作,比如:Object.keys ()、Object.getOwnPropertySymbols ()、Object.getOwnPropertyNames ())
    • 11、preventExtensions (该方法拦截 Object.preventExtensions () ,该方法必须返回个布尔值)
    • 12、setPrototypeOf ( Object.setPrototypeOf 方法 )
    • 13、construct (拦截 new 操作符命令)
  • 若需要在Proxy内部调用对象的默认行为,建议使用Reflect,

    var person = {
     name: "张三"
    };
    
    var proxy = new Proxy(person, {
      get: function(target, propKey) {
        return Reflect.get(target,propKey)
      }
    });
    
    proxy.name // "张三"
    

proxy更多了解,请参考https://mp.weixin.qq.com/s/rIqznB3WXT6M4T0YQb6CQA

Vue3.0 里为什么要用 Proxy API 替代 defineProperty API?

响应式优化。

  • 1、defineProperty API 的局限性,就是它只能针对单个属性做监听
    Vue2.x 中的响应式实现正是基于 defineProperty ,对 data 中的属性做了遍 历 + 递归,为每个属性设置了 getter、setter。 这也就是为什么 Vue 只能对 data 中预定义过的属性做出响应的原因。

    defineProperty的局限性

  • 对于数组来说通过下标的方式直接修改属性的值,或者添加一个预先不存在的属性,是无法监听到数据变化的,

  • 对于对象来说只能劫持对象的属性,从而需要对每个对象的属性进行遍历,如果,属性值是对象,还需要深度遍历。

    这就是 defineProperty 的局限性

  • 2、Proxy API 的监听是针对一个对象的,那么对这个对象的所有操作都会进入监听操作,这就完全可以代理所有属性,将会带来很大的性能提升和代码的优化

    Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须 先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

  • 3、响应式是惰性的

    在 Vue.js 2.x 中,对于一个深层属性嵌套的对象,要劫持它内部深层次的变化,就需要 递归遍历这个对象,执行 Object.defineProperty 把每一层对象数据都变成响应式的,这 无疑会有很大的性能消耗。
    在 Vue.js 3.0 中,使用 Proxy API 并不能监听到对象内部深层次的属性变化,因此它的 处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响 应式,简单的可以说是按需实现响应式,减少性能消耗。

Proxy 区别于 Object.definedProperty
  • 是否可以监听属性的读写、删除、方法的调用
    Object.defineProperty 只能监听到属性的读写,而 Proxy 除读写外,还可以监听属性的删除,方法的调用等。

  • 是否可以监听数组、对象的变化
    Object.defineProperty 无法监测数组、对象的变化。而 Proxy 可以直接监视数组、对象的变化。

    Vue中是通过 对重写数组/对象的方法进行重写来实现监听数组/对象的变化的

  • 监听方式
    Proxy 是以非入侵的方式监管了对象的读写,而 defineProperty 需要按特定的方式定义对象的属性。

    let list = [1, 2, 3];
    let listproxy = new Proxy(list, {
        set(target, property, value) {
            target[property] = value;
            return true; // 标识设置成功
        }
    });
    
    list.push(4);
    
  • Proxy对象可以拦截什么?
    总共13个,见上方。

详细说明参考链接:https://blog.csdn.net/weixin_42724176/article/details/104811337

2、作用域插槽方面

模板方面没有大的变更,只改了作用域插槽,
2.x 的机制导致作用域插槽变了,父组件也会重新渲染
3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。

3、对象式的组件声明方式

Vue2.x 中的组件是通过声明的方式传入一系列 option
Vue3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易。

TypeScript遵循最新的 ES6、 ES5 规范,从语言层面上扩展了JavaScript的语法。 (比如来说,javascript为弱类型语言,而typescript则可以通过类型注释来提供编译时的静态类型检查,从而一定程度上防止报错)

typescript对比javascript,参考链接
https://www.jianshu.com/p/0dfbcd4a0757

4、生成 Block tree

Vue.js 2.x 的数据更新并触发重新渲染的粒度是组件级的。在 2.0 里,渲染效率的快慢与组件大小成正相关:组件越大,渲染 效率越慢。并且,对于一些静态节点,又无数据更新,这些遍历对比就是对性能浪费。

Vue.js 3.0 做到了通过编译阶段对静态模板的分析,编译生成了 Block tree
Block tree 是一个基于动态节点指令将模版进行切割所形成的区块,每个区块内部的节点结构是固定的, 每个区块只需要追踪自身包含的动态节点。所以,在 3.0 里,渲染效率不再与模板大小 成正相关,而是与模板中动态节点的数量成正相关。

5、其它方面的更改

1). 支持自定义渲染器,从而使得 weex 可以通过自定义渲染器的方式来扩展,而不是直接 fork 源码来改的方式。

2). 支持多个根节点

3). 基于 tree shaking进行项目优化,使得项目打包后的体积更小,运行更快。
Tree shaking 是一种通过清除多余代码的方式,来优化项目打包体积的技术,
其原理是基于ES6模板语法(import与exports),在编译时就能确定模块的依赖关系,以及输入和输出的变量。

tree shaking的参考链接:https://www.jianshu.com/p/975073fef572

参考链接:
https://www.jianshu.com/p/4db4b191de06

三、非兼容变更

1、模板指令

  • 组件上 v-model 用法已更改