Vue3 VS Vue2

1.组合式API和选项式API

  • vue2: 采用选项式api
  • vue3: 采用组合式api

1.1 什么是组合式API

Vue3的组合式API是在Vue2的基础上新增的API,它通过提供一组函数式API来让开发者更方便地组合和复用组件逻辑。相较于vue2的选项式API,组合式API更加灵活和易于理解,同时也提供了更好的类型提示和代码重用性。

在这里插入图片描述

1.2 常用的组合式API

  • setup
  • reactive
  • ref
  • computed
  • 生命周期钩子

1.3 Vue3为什么要使用组合式API?

可以更好的逻辑复用:选项式API中我们主要的逻辑复用机制是 mixins ,但是 mixins 又有这三大主要短板:

  • 不清晰的数据来源。
  • 命名空间冲突。
  • 隐式的跨 mixins 交流

1.4 总结

在逻辑组织和逻辑复用方面,组合式API是优于选项式API的。因为组合式API几乎是函数,会有更好的类型推断;组合式API对tree-shaking友好,代码也更容易压缩。组合式API中见不到this的使用,减少了this指向不明的情况,如果是小型组件,可以继续使用选项式API,也是十分友好的。

2.生命周期不同

vue2vue3
创建前beforeCreatesetup
创建后createdsetup
挂载前beforeMountonBeforeMount
挂载后mountedonMounted
更新前beforeUpdateonBeforeUpdate
更新后updatedonUpdated
销毁前beforeDestroyonBeforeUnmount
销毁后destroyedonUnmounted
异常捕获errorCapturedonErrorCaptured
组件被激活activatedonActivated
组件被切换deactivatedonDeactivated

3.TypeScript支持度不同

  • Vue 2:虽然可以使用TypeScript,但支持不够完善,类型推断和类型检查较弱。
  • Vue 3:从设计之初就考虑了TypeScript,提供了更好的类型推断,允许更安全的开发体验。

4.响应式原理不同

特征Vue 2Vue 3
响应式实现使用Object.defineProperty方法来定义对象的gettersetter,以实现数据的响应式;当数据被访问时getter被调用,Vue会记录依赖(即哪些组件使用了这个数据);当数据被修改时,setter被调用,Vue会通知所有依赖该数据的组件进行更新使用Proxy,允许对整个对象进行代理,而不是逐个属性定义gettersetterProxy可以拦截对象的各种操作(如属性读取、修改、添加、删除等),从而实现更全面的响应式。
新属性支持不支持,需要使用Vue.set支持直接添加新属性自动响应
数组索引支持不支持,需使用 spliceVue.set支持数组操作均可触发更新

5.diff算法不同

5.1 vue2中的diff算法

遍历每一个虚拟节点,进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方。用patch记录的消息去更新dom

缺点:
比较每一个节点,而对于一些不参与更新的元素,进行比较是有点消耗性能的。

特点:
Vuepatch是即时的,并不是打包所有修改最后一起操作DOM,也就是在vue中边记录边更新。(React则是将更新放入队列后集中处理)。

5.2 vue3中的diff算法

在初始化的时候会给每一个虚拟节点添加一个patchFlags,是一种优化的标识。只会比较patchFlags发生变化的节点,进行识图更新。而对于patchFlags没有变化的元素作静态标记,在渲染的时候直接复用。

关于diff算法后续我专门写一篇文章讲解!!!

6.Tree-Shaking

‌Vue2不支持Tree Shaking‌:
由于Vue2的源代码是使用CommonJS格式编写的,因此它不支持Tree Shaking。这意味着即使你只使用了Vue的一部分功能,最终打包文件仍然会包含整个Vue库的代码‌。

Vue 3支持Tree Shaking‌:
Vue3的源代码被重写为使用ES Modules格式,这使得Vue3支持Tree Shaking。如果你只使用了Vue的一部分功能,最终打包文件只会包含你实际使用的那部分代码,未使用的代码会被移除。这有助于减小最终打包文件的大小,提高应用的加载性能‌

7.其它

7.1 根节点不同

  • vue2:<template></template>中必须只有一个根标签。
  • vue3:<template></template>可以有多个根标签,会默认将多个根标签包裹在一个fragement虚拟标签中,有利于减少内存。

7.2 创建Vue实例方式不同

vue2:创建Vue实例是通过new Vue()构造函数来实现的,通常是在main.js文件中直接创建应用实例,并将路由和状态管理作为选项传入。

import Vue from 'vue'
import App from './App.vue'
import router from './router';

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

vue3:使用createApp函数来创建应用实例,这使得创建过程更加清晰。路由和状态管理通过use方法进行插件注册。

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
/* 引入createPinia,用于创建pinia */
import { createPinia } from 'pinia'
/* 创建pinia */
const pinia = createPinia()
createApp(App).use(router).use(pinia).mount('#app')

7.3 v-if和v-for的优先级不同

  • vue2v-for的优先级高于v-if,可以放在一起使用,但是不建议这么做,会带来性能上的浪费
  • vue3v-if的优先级高于v-for,一起使用会报错。可以通过在外部添加一个标签,将v-for移到外层

7.4 状态管理

vue2:使用Vuex

const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {  必须通过这里,确保状态的可追踪性
        increment(state) {
            state.count++;
        }
    },
    actions: {
        incrementAsync({ commit }) {
            setTimeout(() => {
                commit('increment');
            }, 1000);
        }
    },
    getters: {
        doubleCount(state) {
            return state.count * 2;
        }
    }
});

vue3:使用Pinia

import { defineStore } from 'pinia';
 
export const useMainStore = defineStore('main', {
    state: () => ({
        count: 0
    }),
    actions: {
        increment() {
            this.count++;
        }
    },
    getters: {
        doubleCount: (state) => state.count * 2
    }
});

7.5 路由管理

vue2:路由通过VueRouter插件进行管理,并在Vue实例中进行注册:

import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
export default new VueRouter({
    mode: 'hash',
    routes: [
        {
            path: '/start',
            name: 'start',
            component: () => import("../components/router/start.vue")
        },    
    ],
})

vue3:仍然使用Vue Router进行路由管理,但通过createRouter函数来创建路由实例,API更加现代化:

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
const routes: Array<RouteRecordRaw> = [
  {
    path: '/about',
    name: 'about',
    component: () => import('../views/AboutView.vue')
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})
export default router

7.6 新的内置组件

  • Fragment
  • Teleport
  • Suspense
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太阳与星辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值