vue3 和 vue2的比较

一、vue3相对于vue2的优化

  1. 类型判断的优化: 由flow.js 改为 typescript。
  2. 数据劫持的优化: 由Object.defineProperty 改为 Proxy, 因为:
    • 对于比较深的对象,Object.defineProperty需要递归遍历所有属性,将所有属性变为响应对象,降低了性能
    • Proxy 对于访问到对象内部的才会变为响应对象
  3. 编译阶段的优化:模版编译的优化、slot的编译优化、事件监听函数的缓存优化及diff算法的重写
    • slot优化,将slot编译为lazy函数,将slot的渲染的决定权交给子组件
    • 模版编译的优:通过编译阶段对静态模板的分析,编译生成了 Block TreeBlock Tree 是一个将模版基于动态节点指令切割的嵌套区块,每个区块内部的节点结构是固定的,而且每个区块只需要以一个 Array 来追踪自身包含的动态节点
    • diff算法重写是因为:vue2中单个组件内,VDOM diff需要遍历整个DOM树,更新需要重新生成DOM树;vue3的VDOM增加静态标记、静态提升、事件缓存,会预先缓存DOM树,通过上下文拿到缓存的DOM树,只diff 动态节点
text
// 静态节点【vue3 和 vue2的比较】text
// 静态节点{{ message }}
// 动态节点text
// 静态节点text
// 静态节点

  1. 逻辑复用的优化:由mixins 改为 hook钩子函数,因为:
    • 定义的变量名容易冲突
    • 变量数据来源不清
// hook import { ref, onMounted, onUnmounted } from 'vue'export default () => { const width = ref(window.innerWidth); const height = ref(window.innerHeight); const update = () => { width.value = https://www.it610.com/article/window.innerWidth; height.value = window.innerHeight; }onMounted(() => { window.addEventListener("resize", update) })onUnmounted(() => { window.removeEventListener("resize", update) })return { width, height } }

二、vue3相对于vue2的变化
  1. 生命周期的变化
vue3 vue2
setup() 开始创建组件 beforeCreate() + created()
onBeforeMount() 组件挂载到页面之前 beforeMount()
onMounted() 组件挂载到页面之后 Mounted()
onBeforeUpdate() 组件更新之前 beforeUpdate()
onUpdated() 组件更新之后 updated()
onBeforeUnmount() 组件卸载之前 beforeDestroy()
onUnmount() 组件卸载之前 destroyed()
onActivated() activated()
onDeactivated() deactivated()
  1. 全局API的变化
## Before import Vue from 'vue' import App from './App.vue'Vue.use(...) Vue.component(...) Vue.prototype.customProperty = ...new Vue({ render: h => h(App) }).$mount('#app')## After import { createApp } from 'vue' import App from './App.vue'const app = createApp(App)app.use(...) app.component(...) app.config.globalProperties.customProperty = ...app.mount('#app')

  1. 全局弹窗
## Before import vue from 'vue' import toastComponent from './toast.vue'const ToastConstructor = vue.extend(toastComponent)function showToast() { const toastDom = new ToastConstructor({...}) }vue.prototype.$toast = showToast## After ...

  1. 子组件向父组件传值
## Before export default { methods: { change() { this.$emit("todata", params); } } }## After export default defineComponent({ emits: ["todata"], setup(props, {emit}) { const change = () => { const params = { user:"ylw" }; emit("todata", params); }; } })

三、组件内的使用
// sfc组件

// jsx组件 import { defineComponent, ref, computed, watchEffect} from 'vue'export default defineComponent({ const numberRef: Ref = ref(1)setup() { const number = numberRef.valuereturn () => { return ({ number }
) } } })

四、Vite和webpack
vite的特性
  • vite是一个基于浏览器原生ES imports的开发服务器
  • 利用浏览器去解析imports,在服务器端按需编译返回,完全跳过了打包这一步,服务器随起随用;而webpack开发环境,需要编译打包es6、es7等,然后启动开发服务器
  • vite支持热更新:vite是按需加载,webpack是全部加载
  • vite依赖es module的特性
vite的打包原理
打包过程 原理
webpack 识别入口->逐层识别依赖->分析/转换/编译/输出代码->打包后的代码 逐级递归识别依赖,构建依赖图谱->转化AST语法树->处理代码->转换为浏览器可识别的代码
vite - 基于浏览器原生 ES module,利用浏览器解析 imports,服务器端按需编译返回
vite的改进点
webpack缺点 vite改进点
服务器启动缓慢 将应用模块区分为依赖 和 源码 两类; 使用esbuild构建; 在浏览器请求源码时进行转换并按需提供源码
基于nodejs esbuild(Go 编写) 预构建依赖,比node快 10-100 倍
热更新效率低下; 编辑单个文件会重新构建整个包; HMR 更新速度随规模增大下降 HMR基于原生 ESM 上,更新速度与应用规模无关; 利用http2的缓存+压缩优势
vite的缺点
  • 生态不及webpack,加载器、插件不够丰富
  • 生产环境esbuild构建对于css和代码分割不够友好
  • 没被大规模重度使用,会隐藏一些问题

    推荐阅读