vue2和Vue3对比分析

这篇文章主要介绍了vue2和Vue3对比分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇vue2和Vue3对比分析文章都会有所收获,下面我们一起来看看吧。

目前创新互联建站已为上千的企业提供了网站建设、域名、雅安服务器托管、网站改版维护、企业网站设计、高安网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

vue2和Vue3对比分析

Vue2 vs Vue3


1、简单点说

  • Vue2只支持单节点,Vue3 template支持多节点,类似react fragments

  • 变化基本都在script中(Option api -> Composition api)不会再看见满屏的this了!!!

  • style支持v-bind

  • Proxy代替defineProperty

    • defineProperty无法实现对数组对象的深层监听,Proxy是浏览器最新api,功能更加强大。

    • 不再支持IE,Vue2想享受Vue3带来的部分更新,可考虑升级Vue2.7版本

  • TypeScript的支持

    • Vue2采用的是Facebook的Flow,没法完美支持TypeScript(所以项目初期技术选型很重要)

    • Vue3 TypeScript完全重写,提供和React一样的TS支持

  • 全新生态

    • 基本还是vue周边伴随Vue3升级那一套,但是状态管理推荐,由原来的Vuex变为Pina

    • 全新的vite支持,包括vitest等,官方提供周边工具更多了

  • 其它优化

    • 性能更好,体积更小就不用说了

    • 事件监听缓存,类似@click绑定的函数,无需多次创建,放在了cacheHandler缓存中

    • SSR:Vue 3.0 会将静态标签直接转化为文本,相比 React 先将 JSX 转化为虚拟 DOM,再将虚拟 DOM 转化为 HTML,这一点Vue3的速度要快很多

    • Use Hooks 放弃过去的mixins,使用Hooks解决过去mixins的一些缺点

2、源码

diff算法的优化
  • 不再和vue2一样,完全对比两棵虚拟DOM树,Vue3采用动静结合的方法,优化diff性能

  • 通过编译阶段对静态模板进行分析,编译生成 Block tree。更新性能由 模版整体大小相关 =》与动态内容的数量相关,这是一个非常大的性能突破。将代码提升到渲染函数之外,这样可以避免在每次渲染时重新创建这些对象,从而大大提高内存使用率并减少垃圾回收的频率。

源码管理
  • vue2 poly-repo

    • vue2.x的源码托管在src目录中,然后依据功能拆分出了complier(模板编译的相关代码),core(与平台无关的通用运行时代码),platforms(平台专有代码),server(服务端渲染的相关代码)、sfc(.vue 单文件解析相关代码)、shared(共享工具代码) 等目录

  • vue3 mono-repo

    • package可以独立于vue.js去使用,这样例如用户想要使用vue3.0的响应式,可以单独依赖reactive,而不必依赖整个vue.js,减少引用包的体积,而vue2.x却做不到这一点。

  • 源码结构对比

vue2和Vue3对比分析

全新的API


什么是组合式 API?- Vue官方

  • 解决了过去组件过长时,optionsApi带来的难以维护的问题

  • 逻辑可以整块复用

  • 所有API都是import引入的,对Tree- shaking很友好,没用到功能,打包的时候会被清理掉,减小包的大小

1、setup

  • 新的 setup 选项在组件被创建之前执行,一旦 props 被解析完成,它就将被作为组合式 API 的入口。

  • 可以当做Vue2的beforeCreate和create生命周期用

  • 可直接写await语法

  • SFC单文件组件中直接使用 // or  export default {   setup(props, context) {     // Attribute (非响应式对象,等同于 $attrs)     console.log(context.attrs)     // 插槽 (非响应式对象,等同于 $slots)     console.log(context.slots)     // 触发事件 (方法,等同于 $emit)     console.log(context.emit)     // 暴露公共 property (函数)     console.log(context.expose)   } }

    2、ref

    • ref 用来创建基础类型的响应式数据

    • template中默认调用value显示数据,script中需要使用.value 调用

    • 和react ref差不多,react是.current获取值,vue3是.value。

    • Ref的本质是通过Reactive创建的,Ref(10)=>Reactive({value:10})

    有一定的心智负担,尤大也明确说了不会支持script中直接访问。究其原因,还是基础类型无法拦截它的变化,当然也有大哥提出用new String('foo')类似的语法对基础类型进行包装。个人感觉直接拿已支持的reactive来搞也不错

    相关api
    • Ref ts定义 import { type Ref } from 'vue';

    • isRef  判断是否为ref对象。一般是ref,toRef,toRefs创建的变量

    • toRefs 将reactive对象解构为单个响应式对象

    • shallowRef 创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的,简单理解为创建一个和ref相同结构的非响应式变量

    • triggerRef 强制更新页面DOM。即使创建的ref没有变,想更新dom可以用

    • customRef 提供类似于computed的get和set,可自定义ref行为

    3、reactive

    • reactive 用来创建引用类型的响应式数据

    • reactive的本质是将每一层的数据都解析成proxy对象

    • reactive 的响应式默认都是递归的,改变某一层的值都会递归的调用一遍,重新渲染dom。

    • 直接解构,响应性会丢失,需要用toRefs包裹。引用类型直接改变引用地址也会导致响应式丢失

    相关api
    • readonly 将reactive的值更改为只读

    • shallowReactive  只能对浅层的数据响应 如果是深层的数据只会改变值 不会改变视图

    import { reactive, toRefs } from 'vue'
    
    const book = reactive({
      author: 'Vue Team',
      year: '2020',
      title: 'Vue 3 Guide',
      description: 'You are reading this book right now ;)',
      price: 'free'
    })
    
    let { author, title } = toRefs(book)
    
    title.value = 'Vue 3 Detailed Guide' // 我们需要使用 .value 作为标题,现在是 ref
    console.log(book.title) // 'Vue 3 Detailed Guide'

    4、生命周期

    区别不大,把setup当created用,其它就当改了个名

    
    import { onMounted } from 'vue';
    
    const getUserInfo = () => {
      console.log('获取用户信息');
    };
    onMounted(getUserInfo);
    

    vue2和Vue3对比分析

    5、watch & watchEffect

    watch
    • 功能和vue2一致

    • watch(监听参数,变化回调,配置参数)

    • 注意监听对象的单个属性:watch(() => articleInfo.author, (newVal) => {}),第一个参数为箭头函数返回要监听的目标属性

    import { ref, reactive, watch } from 'vue'
    
    const counter1 = ref(0)
    const counter2 = ref(0)
    // 监听多个
    watch([counter1, counter2], (newValue, oldValue) => {
      console.log('The new counter1 value is: ' + counter1.value)
      console.log('The new counter2 value is: ' + counter2.value)
    })
    
    const obj = reactive({
      name: 'JJ',
      age: 18
    })
    // 深度监听对象
    watch(obj, (newValue, oldValue) => {
      console.log('The new obj value is: ' + obj.value)
    }, {
       deep: true,
       immediate: true
    })
    // watch监听单个属性
    watch(() => obj.name, (newValue, oldValue) => {
      console.log('The new obj value is: ' + obj.value)
    }, {
       deep: true,
       immediate: true
    })
    watchEffect
    • 类似React useEffect,但是不需要写依赖项,只要我们回调中引用了 响应式的属性

    • 和watch的区别:

      • 同一个功能的两种不同形态,底层的实现是一样的

      • watch 可以获取到新值与旧值(更新前的值),而 watchEffect 是拿不到的。

      • watch - 显式指定依赖源,watchEffect - 自动收集依赖源

      • watchEffect 在组件初始化的时候就会执行一次用以收集依赖,watch指定了依赖,所以不需要。

      • 可以理解为watchEffect 就是配置了{ immediate: true } 的watch

    • 使用场景:antfu小哥:推荐在大部分时候用 watch 显式的指定依赖以避免不必要的重复触发,也避免在后续代码修改或重构时不小心引入新的依赖。watchEffect 适用于一些逻辑相对简单,依赖源和逻辑强相关的场景(或者懒惰的场景 )。

    const stopWatch = watchEffect(
      (oninvalidate): void => {
        oninvalidate(() => {
          console.log("前置校验函数");
        });
        // 引用了响应式的属性 count
        console.log("watchEffect count变化", count.value);
      },
      {
        // 副作用刷新时机 flush 一般使用post
        // 可选:pre(组件更新前执行)/sync(强制效果始终同步触发)/post(组件更新后执行)
        flush: "post",
        // 开发调试
        onTrigger() {
          console.log("开发调试");
        },
      }
    );

    6、computed

    • 更加灵活,可以在定义响应式变量时声明

    • 作用和vue2无差异

    import { ref, computed } from 'vue'
    
    const counter = ref(0)
    const twiceTheCounter = computed(() => counter.value * 2)
    // get set写法
    const plusOne = computed({
      get: () => counter.value + 1,
      set: (val) => {
        counter.value = val - 1
      },
    })
    
    plusOne.value = 1
    console.log(counter.value) // 0
    
    counter.value++
    console.log(counter.value) // 1
    console.log(twiceTheCounter.value) // 2

    组件


    1、异步组件

    • 通过进行引入defineAsyncComponent

    • 可配合Suspense 进行更多操作,可用于loading和骨架屏相关,和react Suspense基本一致。不过react Suspense基本一致这个属性都不太好用,vue的不清楚实际场景咋样

    // template
    
      
        
      
    
      
        
    loading...
      
    // script const AsyncComponent = defineAsyncComponent(() => import('./asyncComponent.vue'))

    2、Teleport传送组件

    Teleport 是一种能够将我们的模板渲染至指定DOM节点,不受父级style、v-show等属性影响,但data、prop数据依旧能够共用的技术;类似于 React 的 Portal。之前写react是不怎么用这个属性,vue3这个估计也没多大用。

    主要解决的问题 因为Teleport节点挂载在其他指定的DOM节点下,完全不受父级style样式影响

    to 属性 插入指定元素位置,body,html,自定义className等等

    
        
    

    3、keep-alive缓存组件

    • 作用和vue2还是一样的,生命周期名称变了

    • 初次进入时:onMounted> onActivated

    • 退出后触发 deactivated

    • 再次进入:只会触发 onActivated

    4、组件通信

    defineXxxx

    defineXxxx 无需import即可直接使用

    • defineProps 代替过去的props

    • defineEmits 代替过去的$emit

    • defineOptions 自定义一些组件属性,比如组件名称(需要插件支持)

    • defineComponent 用于render函数、TSX、IDE提醒等

    • defineExpose 子组件声明的数据,暴露给父组件直接用

    provide/inject

    和vue2一致

    vuex & pina

    两者用法,除了pina没有Mutations,差别不大。但是官方推荐的东西,自然有它的各种优点

    • Vuex: State、Gettes、Mutations(同步)、Actions(异步)

    • Pinia: State、Gettes、Actions(同步异步都支持)

    • Vuex4 用于 Vue3 ,Vuex3 用于 Vue2

    • Pinia2.x 即支持 Vue2 也支持 Vue3

    TS支持


    • 可以让写react的兄弟,快速上手写vue3

    • react中 {{}} => {}

    • 兼容的指令:v-model,v-if,v-show

    import { ref } from 'vue'
    let v = ref('')
    const renderDom = () => {
        return (
            <>
               
               
                   {v.value}            
                 ) } export default renderDom

    插件


    1、开源插件

    unplugin-auto-import/vite

    无需导入xxx,import { reactive,ref } from "vue";,只需要用即可

    unplugin-vue-define-options

    自定义组件名称,需要引入插件unplugin-vue-define-options,并在vite中配置

    import { defineConfig } from 'vite';
    import vue from '@vitejs/plugin-vue';
    import DefineOptions from 'unplugin-vue-define-options/vite';
    
    export default defineConfig({
      plugins: [vue(), DefineOptions()],
    });

    不使用插件,也可以通过多写一个script标签来单独写options

    
    
      defineOptions({
        name: 'TButton',
      });
    

    2、vscode插件

    volar vscode
    • vetur只支持vue2,volar只支持vue3,两者冲突。

    • 建议禁用vetur,格式化代码使用prettier,本地使用volar做代码高亮。

    • 或者通过项目配置,指定相关插件配置

    vue2和Vue3对比分析

    指令


    1、v-model

    • 底层语法糖时间改变,之前vue2是update:input,vue3 是update:modelValue

    • 支持多个v-model

    • 支持自定义修饰符

    • 弃用.sync等

    2、自定义指令

    生命周期(和vue3一致)
    • created 元素初始化的时候

    • beforeMount 指令绑定到元素后调用 只调用一次

    • mounted 元素插入父级dom调用

    • beforeUpdate 元素被更新之前调用

    • update 这个周期方法被移除 改用updated

    • beforeUnmount 在元素被移除前调用

    • unmounted 指令被移除后调用 只调用一次

    自定义拖拽指令v-move
    • 比如这个v-move 封装自定义拖拽指令

    import { Directive } from "vue";
    const vMove: Directive = {
      mounted(el: HTMLElement) {
        let moveEl = el.firstElementChild as HTMLElement;
        const mouseDown = (e: MouseEvent) => {
          //鼠标点击物体那一刻相对于物体左侧边框的距离=点击时的位置相对于浏览器最左边的距离-物体左边框相对于浏览器最左边的距离
          console.log(e.clientX, e.clientY, "-----起始", el.offsetLeft);
          let X = e.clientX - el.offsetLeft;
          let Y = e.clientY - el.offsetTop;
          const move = (e: MouseEvent) => {
            el.style.left = e.clientX - X + "px";
            el.style.top = e.clientY - Y + "px";
            console.log(e.clientX, e.clientY, "---改变");
          };
          document.addEventListener("mousemove", move);
          document.addEventListener("mouseup", () => {
            document.removeEventListener("mousemove", move);
          });
        };
        moveEl.addEventListener("mousedown", mouseDown);
      },
    };

    Hook


    用了react hook的人都知道很香,vue3支持这个相当不错,能解决很多业务场景的封装

    1、自定义Hook

    可以当做mixins写

    // useWindowResize
    import { onMounted, onUnmounted, ref } from "vue";
    
    function useWindowResize() {
      const width = ref(0);
      const height = ref(0);
      function onResize() {
        width.value = window.innerWidth;
        height.value = window.innerHeight;
      }
      onMounted(() => {
        window.addEventListener("resize", onResize);
        onResize();
      });
      onUnmounted(() => {
        window.removeEventListener("resize", onResize);
      });
      
      return {
        width,
        height
      };
    }
    
    export default useWindowResize;

    2、hook库

    • vueuse 官方,感谢评论区@rogepi 小哥的提醒

    • ahooks-vue

    • v3hooks

    3、react vs vue3

    • Vue3 究竟好在哪里?(和 React Hook 的详细对比)

    vue2和Vue3对比分析

    关于“vue2和Vue3对比分析”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“vue2和Vue3对比分析”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注创新互联行业资讯频道。


    文章标题:vue2和Vue3对比分析
    转载来于:http://scjbc.cn/article/ppgjjc.html