Vue3与Vue2的区别

332 阅读6分钟

@vue/cli 创建Vue2/3的工程化项目 Vue2全家桶

  • Vue@2
  • Vuex@3
  • Vue@router@3
  • Vant@2 移动端UI组件库
  • element-ui PC端UI组件库

Vue3全家桶

  • vue@3

  • Vuex@4

  • Vue-router@4

  • vant@3

  • element-plus

Vue2和Vue3的区别

Vue3的新特性

1.performance

性能上做了提高[内部重写了虚拟DOM的实现,在虚拟DOM处理的时候,跳过静态节点,只处理动态节点] 结果就是客户端渲染视图的速度提高了1.3倍到2倍之间,而服务端SSR渲染的速度提高了2~3倍

Vue视图渲染的机制 基于template/jsx语法构建视图 --> 会把视图编译为虚拟DOM对象(vnode:vue内部构建的对象,用来描述节点相关的属性特征)

-->如果是第一次渲染,会直接虚拟DOM变为真实DOM(真实DOM:放入到浏览器页面中进行渲染)

-->如果是视图更新,会重新生成虚拟DOM,和上一次生成的虚拟DOM进行对比[DOM-diff] 同级对比 由上而下比较 计算出差异的部分,再渲染的时候,只需要把有差异的部分进行渲染即可。

Vue2:基于Vue-template-compiler 这个插件实现对template视图的编译 把其编译为vnode Vue3:基于@vue/compiler-sfc这个插件实现对视图的编译

2.Tree shaking

利用webpack新版本自带的功能实现"打包优化":把没有用到的API自动剪辑掉 只打包用到的内容!! 例如:utils库中100个方法 但是项目中我们直接或间接使用的只有20个 如果"Tree shaking机制" 我们打包的还是100个方法(这样没有必要,而且文件体积还会变大) 如果具备这个机制 只会打包20个方法 打包速度变快 打包后的体积也会更小... 对于UI组件库,一般都提供了单独的"按需导入"

3.Fragment

Vue2的template视图中 只允许出现一个根节点 会导致层级过深 Vue3的template视图中 可以出现多个根节点 原理:它自己在外层嵌套Fragment空文档标记标签<></> 不占DOM层级 还能保证只有一个根节点

如果vscode报红

  • 效果可以实现
  • 你的vscode不支持vue3的语法

更新系统「win10/11」 安装最新版本的vscode 保证Vetur也是最新版本

4.新增内置组件 <Teleport> :传送门

正常情况下,组件内部所有内容在编译完成后,都会插入到#app中渲染!! 传送门机制,可以让组件中的某一部分内容,插入到#app以外的其他容器中渲染

image.png image.png

5.新增内置组件 : 异步组件

/* 在子组件中*/
<template>
    <ul>
        <li v-for="(item, index) in list" :key="index">
            {{ item }}</li>
    </ul>
</template>

<script>
import { defineComponent } from 'vue';
const query = function query() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve([11, 22, 33])
        }, 2000)
    })

}
export default defineComponent({
    /* 第一次渲染组件会执行setup */
    async setup(props) {
        let list = await query();
        /* 等待两秒后才会返回list  此时组件不会渲染 */
        return {
            list,
        };
    }
})
</script>

/*在父组件中*/
<template>
    <Suspense>
        <SuspenseTest></SuspenseTest>
        <template #fallback>
            <el-skeleton :row="3" animated></el-skeleton>
        </template>
    </Suspense>
</template>

<script setup>
import SuspenseTest from './views/SuspenseTest.vue';
</script>

6.更好的支持Typescript 有一些公司,已经开始采用 vite+vue3+ts 组合做开发了

7.Custom Renderer API

一般情况下 我们在视图(组件)中编写的内容都会以HTML的形式插入到页面中! Custom Renderer API中提供了一系列的方法 可以让我们在组件中编写的内容 最后绘制为对应的图形图片(canvas)以此更好的实现可视化的开发

8.Composition API

在Vue2中 我们采用的是"options API" 在Vue3中 我们也可以继续延续"options API"的写法 但是建议大家使用"Compositions API 聚合式API" 把所有的内容基本上都写在setup函数中

export default{
   setup(){
       ....
   }
}

<script setup></script>

9.在Vue3中 推荐使用"函数式编程"

Vue3中 不再有Vue这个类所以也就不存在 new Vue({})这样的操作了 而是要导出createAPP这个函数 基于这个函数执行创建对应的应用

Vue2 面向对象的方式
new Vue({
     store,
     router,
     h=>h(APP)
})
Vue3 函数式编程
import {createApp} from 'vue'
const app = createApp(APP);
app.use(store);
app.use(router);
app.mount(#app);

10.响应式数据实现的方案做了改变

Vue2的响应式原理:基于defineproperty对数据进行劫持

Vue3的响应式原理 两种方案

以ref为主的响应式方案  依然式基于defineProperty做数据劫持

以reactive为主的响应式方案  记忆ES6的Proxy实现数据劫持

Vue3中的响应式原理: 
       @1 以ref为主的get/set劫持「核心还是Object.defineProperty」
       @2 以reacive为主的数据劫持,是基于ES6中的Proxy实现的
       特点:
       + 直接对整个对象进行代理劫持,而且对于数组每一项也是直接劫持 -> Vue3的响应式性能要强于Vue2
       + 除了做get/set劫持外,还可以实现其它方面的劫持:getPrototypeOf/setPrototypeOf/isExtensible/preventExtensions/getOwnPropertyDescriptor/defineProperty/has/deleteProperty/ownKeys/apply/construct,Vue3中实现了get/set/deleteProperty/has/ownKeys等劫持 -> Vue3响应式实现的功能要强于Vue2
       + 也像Vue2一样,基于递归对“对象”做了深层次劫持
       + ES6新增的API,不兼容IE

     Vue2中的响应式原理:
       + 首先对data进行深度的监听和劫持  Object.defineProperty「ES5」
       + 对数组每一项不进行处理,而是重写了数组的原型指向「push/pop/shift/unshift/splice/sort/reverse」
       特点:
       + 对“对象”中的每一项只做了get/set的劫持,只有获取及修改属性值的时候,才会触发劫持函数
       + 依次迭代对象中的每个属性,给每个属性分别做劫持
       + 对于数组每一项只是重写了原型对象,但是没有做劫持
         obj.z=[...]  视图会更新
         obj.z[0]=100 视图不会更新
         obj.z.splice(0,1,100) 视图会更新
       + 基于递归把每一次层级都做了劫持
       + ES5劫持方法,所以兼容IE9+
       + 如果当前对象是被冻结的,则不进行劫持处理



虽然在Vue3中依然可以延续Vue2的语法 但是每一个组件(this)不在Vue类的实例 也访问不到Vue。prototype 去掉了面向对象的相关特征 常用的一些属性方法变为this的私有属性 data/methods/computed...这里编写状态/方法/计算属性 也会挂载到实例上 视图中也可以直接使用


但是类似于我们之前 在Vue.prototype.api在组件中this.api 在组件中 this.api.xxx 无法使用了

Vue3中建议使用"聚合式API":编写的内容(例如:状态、计算属性、方法、监听器....)都聚合在setup函数中

@1 只有第一次渲染组件的时候才会触发setup函数执行 【组件更新的时候不会触发】

@2 发生在"初始化props"之后 和"beforeCreate"之前

  + this --> undefined   聚合式API的模式下  我们告别了基于this操作的的时代
  + 我们可以基于props形参 获取到处理过的属性 【而且属性兑现是经过Proxy做过数据劫持的响应式数据】
  不仅可以在setup中获取到  一样延续Vue2的处理 也会把属性挂载到this上一份  在视图上也可以直接使用
  + 在setup函数中基于return返回的内容  都会默认挂载到this上【虽然setup中没有this】这样也就可以直接在视图中使用了;

  + setup 函数中也并不会聚合所有东西 例如:
    + 组件的名字
    + 属性初始化
    + 注册组件
    + 注册使用上下文信息
    + ...