跨越时代的框架对决:深度剖析Vue 2与Vue 3核心差异

简介: 跨越时代的框架对决:深度剖析Vue 2与Vue 3核心差异

🌟 Vue2与Vue3 的区别


随着前端技术的日新月异,Vue.js框架也迎来了它的重大变革——Vue3!从Vue2到Vue3,不仅仅是一次版本更新,更是对性能、可维护性和开发体验的一次全面提升🔥🚀。今天,我们一起深入探讨两者之间的核心区别,配合实战代码片段,让你轻松掌握Vue3的革新之处✨!

🔮 双向数据绑定:Object.defineProperty vs Proxy

Vue2通过Object.defineProperty实现了经典的双向数据绑定机制💡:

// Vue2
const vm = new Vue({
  data: {
    message: 'Hello Vue2!'
  }
});
console.log(vm.$data.message); // 输出 "Hello Vue2!"
vm.message = 'Hello Vue3!';

而Vue3采用Proxy实现更为高效的数据代理🌟:

// Vue3 使用 composition API
import { reactive } from 'vue';
const state = reactive({ message: 'Hello Vue3!' });
console.log(state.message); // 输出 "Hello Vue3!"
state.message = 'Hello Future!';

Proxy的优势在于能够一次性代理整个对象,无需遍历属性,且能更好地处理数组的变化,无需手动调用 $set 方法来确保响应式 TencentWeibo;


🎨 组件化:Options API vs Composition API

Vue2中的组件结构依赖于Options API

// Vue2
export default {
  data() {
    return {
      count: 0,
    };
  },
  computed: {
    doubleCount() {
      return this.count * 2;
    }
  },
  methods: {
    increment() {
      this.count++;
    }
  },
};

Vue3引入了Composition API,让逻辑组织更灵活,便于复用和单元测试:

// Vue3
import { ref, computed } from 'vue';
export default {
  setup() {
    const count = ref(0);
    
    const doubleCount = computed(() => count.value * 2);
    function increment() {
      count.value++;
    }
    return {
      count,
      doubleCount,
      increment
    };
  }
};

💡 生命周期钩子函数调整

Vue2中的生命周期钩子函数在Vue3中进行了精简和重组:

// Vue2
export default {
  beforeCreate() {},
  created() {},
  beforeMount() {},
  mounted() {},
  // ...
};
// Vue3
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated } from 'vue';
export default {
  setup() {
    onBeforeMount(() => {});
    onMounted(() => {});
    onBeforeUpdate(() => {});
    onUpdated(() => {});
  }
};

🌲 Tree Shaking 和渲染优化

Vue3带来了更好的Tree Shaking能力,允许构建工具丢弃未使用的代码片段,减小打包体积💪。同时,Vue3内部的编译器和运行时经过重构,组件渲染算法得到优化,提升了应用整体性能💨。


🎯 Fragments

在Vue2中,每个组件必须有一个单一的根元素。而在Vue3中,引入了Fragments特性,允许一个组件返回多个顶级元素,无需包裹层元素,简化模板结构🎯:

<!-- Vue2 -->
<template>
  <div>
    <h1>Title</h1>
    <p>Paragraph 1</p>
    <p>Paragraph 2</p>
  </div>
</template>
<!-- Vue3 -->
<template>
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

🚀 Teleport

Vue3新增的Teleport指令,允许我们将组件的内容渲染到DOM树的任何位置,常用于模态框、提示信息等需要跳出当前上下文渲染的情况🌏:

<!-- Vue3 -->
<template>
  <teleport to="#modal-container">
    <modal v-if="showModal">This is a modal!</modal>
  </teleport>
</template>

⏳ Suspense

Vue3引入了Suspense组件,用来优雅地处理异步组件的加载和错误状态。当异步组件还未加载完成时,Suspense组件内的fallback内容将会被展示,提升用户体验⏰:

<template>
  <suspense>
    <template #default>
      <async-component />
    </template>
    <template #fallback>
      <loading-spinner /> <!-- 加载中... -->
    </template>
  </suspense>
</template>

📊 性能优化与编译器改进

Vue3内部的编译器和运行时进行了大量优化,包括:

  • 编译优化:Vue3采用了新的编译器@vue/compiler-sfc,使得模板编译更快、更准确;
  • 运行时优化:通过FragmentTeleport等减少不必要的 DOM 操作,提高渲染效率;
  • 基于Proxy的响应系统:相比Vue2的Object.defineProperty,Vue3的响应系统性能更高,尤其是针对大型对象和数组的监听;
  • v-for的key改进:Vue3对于 v-for 的 key 值有更严格的校验,帮助避免不必要的重渲染问题;
  • Fragment、Teleport等特性:这些特性降低了额外 DOM 元素的创建,提高了渲染性能和DOM结构清晰度。

🌈 TypeScript 更完善的集成

Vue3全面支持TypeScript,提供了官方的声明文件和类型提示,不仅使开发者能够写出类型安全的代码,还增强了IDE自动补全和错误检测的能力💪📚。


🛠 Vuex 更新:Pinia 的兴起

Vue3并未直接在核心库中提供Vuex的新版本,而是推荐使用社区驱动的Pinia作为状态管理库。Pinia借鉴了Vue3的Composition API设计,使得状态管理和组件内逻辑更加统一和简洁便利🛠️:

// 安装Pinia
import { createApp } from 'vue';
import { createPinia } from 'pinia';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
// 创建store
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
  }),
  actions: {
    increment() {
      this.count++;
    },
  },
});
// 在组件中使用
import { useCounterStore } from './stores/counter';
export default {
  setup() {
    const counter = useCounterStore();
    
    function handleClick() {
      counter.increment();
    }
    return {
      handleClick
    };
  }
};

🎮 渲染函数 API 的变化

Vue3在渲染函数上也有显著变化,采用了新的setupRenderFunctions方法替代Vue2的render函数。它结合了setup函数,允许我们在同一个地方定义props、emit、context和渲染逻辑🎮:

import { h, defineComponent } from 'vue';
export default defineComponent({
  setup(props, context) {
    // 访问props和emit
    const { foo } = props;
    const { emit } = context;
    // 返回渲染函数
    return () => h('div', {}, `Prop value: ${foo}`);
  },
  props: {
    foo: String
  }
});

🌐 Vue Router 更新

Vue Router 4.x 针对Vue3进行了适配和优化,使用新的Composition API风格,路由守卫和导航钩子的使用方式也有所改变🌐:

import { createRouter, createWebHistory } from 'vue-router';
import { useRoute, useRouter } from 'vue-router';
const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About },
  ],
});
// 在组件中使用
export default {
  setup() {
    const route = useRoute();
    const router = useRouter();
    // 声明导航守卫
    router.beforeEach((to, from, next) => {
      // ...
    });
    return {
      route,
      router
    };
  }
};

🤖 Web Components 支持

Vue3现在提供了更好的原生Web Components兼容性,可以通过defineCustomElement方法将Vue组件转换为自定义元素,以便与非Vue项目或不同的前端框架无缝集成🤖:

import { defineComponent } from 'vue';
import { defineCustomElement } from 'vue/dist/vue.esm-bundler.js';
const MyVueComponent = defineComponent({
  template: '<div>Hello from Vue Component!</div>'
});
customElements.define('my-vue-component', defineCustomElement(MyVueComponent));

🍃 自定义指令的变更

Vue2 中,我们使用 Vue.directive 注册全局自定义指令,而在 Vue3 中,全局指令注册移到了 app.directive 上,语法略有不同,增加了 setup 函数以利用 Composition API:

// Vue2
Vue.directive('my-directive', {
  bind(el, binding, vnode) {
    el.style.color = binding.value;
  }
});
// Vue3
const app = createApp(App);
app.directive('my-directive', {
  beforeMount(el, binding) {
    el.style.color = binding.value;
  },
  updated(el, binding) {
    el.style.color = binding.value;
  }
});

🎭 模板引用的改动

Vue2 中我们通过 ref 属性并在父组件中通过 $refs 访问 DOM 元素。Vue3 引入了 .value 来访问 ref 对象的底层 DOM 节点或组件实例:

<!-- Vue2 -->
<input ref="inputRef">
<script>
export default {
  mounted() {
    console.log(this.$refs.inputRef);
  }
};
</script>
<!-- Vue3 Composition API -->
<input ref="inputRef">
<script setup>
import { ref } from 'vue';
const inputRef = ref(null);
onMounted(() => {
  console.log(inputRef.value);
});
</script>

🎨 动画过渡系统的增强

Vue3 过渡系统仍然支持 transition 组件和相应的 CSS 类名,但新增了 <Transition><TransitionGroup> 组件,可以更好地与 Composition API 结合使用:

<!-- Vue2 -->
<transition name="fade">
  <div v-if="show">Fade in/out</div>
</transition>
<!-- Vue3 Composition API -->
<Transition name="fade">
  <div v-if="show">Fade in/out</div>
</Transition>

📡 Provide / Inject 的变化

Vue3 提供了一个新的 provide/inject 实现,可以与 Composition API 更好地配合,不再局限于全局作用域:

// Vue2
Vue.prototype.$theme = 'dark';
// 子组件
this.$parent.$theme; // 'dark'
// Vue3 Composition API
setup() {
  const theme = inject('theme', 'light');
  provide('theme', 'dark');
  return { theme };
}

🔍 DevTools 更新

Vue DevTools 工具针对 Vue3 进行了全面升级,提供了更友好的界面和更详细的组件状态追踪功能,极大提高了调试效率和开发体验🔍:


💼 打包工具及优化

Vue CLI 的更新

Vue2 主要搭配的是 Vue CLI 2 或 Vue CLI 3,而随着 Vue3 的发布,Vue CLI 也升级到了 Vue CLI 4 及更高版本,它集成了对 Vue3 的开箱即用支持,并且整合了更多现代前端构建工具链的特点,如 Webpack 5(后续版本)以及 Tree Shaking 等优化技术。

Vue CLI 4 及以后版本提供的 @vue/cli-service 包含了对 Vue3 项目的默认配置,开发者无需手动配置就能快速搭建项目并享受到最新的构建和打包优势。

Rollup 与 Vite 的引入

Vue3 同时推荐使用 Vite 作为新一代的开发工具,Vite 使用了 Rollup 作为其打包器,相比于传统的 Webpack,Vite 在开发环境提供了更快的热更新速度和更轻量级的启动时间。Vite 利用 ES 模块原生加载能力,在开发阶段直接基于源码进行按需编译,大大提升了开发效率。

Tree Shaking 加强

Vue3 引入了更细粒度的打包策略,使得 Tree Shaking 更加有效。尤其是在使用 Vue3 的 Composition API 时,由于函数式的模块化设计,更容易被打包工具识别并移除未使用的代码片段,从而减小生产环境下的 JavaScript 包体积。

Scope Hoisting 优化

Webpack 和 Rollup 都支持 Scope Hoisting 技术来优化产出的 bundle 文件,通过此技术,Vue3 项目的多个模块会被合并到一个闭包中,减少函数声明和变量提升带来的开销,进而提高运行时性能。

压缩与分包策略

Vue CLI 和 Vite 都支持各种压缩工具(如 TerserWebpackPlugin 或者 esbuild)对最终生成的代码进行压缩,同时允许开发者自定义 chunk 分割策略,以便实现动态加载和延迟加载,进一步优化首屏加载速度。

目录
相关文章
|
2天前
|
缓存 JavaScript 前端开发
前端框架与库 - Vue.js基础:模板语法、数据绑定
【7月更文挑战第14天】Vue.js 是渐进式框架,以简洁API和高效数据绑定知名。本文聚焦模板语法与数据绑定,解释常见问题和易错点,助力初学者避坑。模板语法中,{{ expression }} 用于渲染值,v-bind/: 用于动态绑定属性。数据绑定涉及文本、属性和事件,注意v-model适用于表单元素,计算属性有缓存。理解正确用法,借助文档和IDE,可提升开发质量和效率。善用Vue.js,打造响应式UI。
|
1天前
|
JavaScript 前端开发 API
前端框架与库 - Vue.js 组件与路由
【7月更文挑战第15天】Vue.js 框架以简洁API和高效DOM更新著名,组件和路由是构建应用的关键。组件是自包含的实例,常见问题包括命名冲突、作用域混淆和状态管理。要避免这些问题,可使用命名空间、明确数据绑定和事件,以及采用Vuex管理状态。Vue Router提供声明式路由,常见挑战包括路由守卫、动态路由参数和懒加载配置。正确使用路由守卫、处理动态参数和实现代码分割能优化路由管理。提供的代码示例展示了基本组件和路由配置。
|
5天前
|
JavaScript
【vue】 vue2 监听滚动条滚动事件
【vue】 vue2 监听滚动条滚动事件
12 1
|
5天前
【vue3】Argumnt of type ‘history:RouterHistory;}is not assignable to paraeter of type ‘RouterOptions‘.
【vue3】Argumnt of type ‘history:RouterHistory;}is not assignable to paraeter of type ‘RouterOptions‘.
6 0
|
5天前
|
JavaScript
【vue3】vue3中路由hash与History的设置
【vue3】vue3中路由hash与History的设置
11 0
|
5天前
|
编解码 前端开发
【Vue3】解决电脑分辨率125%、150%及缩放导致页面变形的问题
【Vue3】解决电脑分辨率125%、150%及缩放导致页面变形的问题
24 0
|
5天前
|
JavaScript
【vue】 vue 翻页时钟制作,vue2、vue3
【vue】 vue 翻页时钟制作,vue2、vue3
11 0
|
1天前
|
JavaScript
vue知识点
vue知识点
13 5
|
3天前
|
JavaScript
|
5天前
|
JavaScript
【vue】el-dialog 内的tinymce弹窗被遮挡的解决办法 及 tinymce打开弹出菜单后直接关闭对话组件,导致该弹出菜单残留
【vue】el-dialog 内的tinymce弹窗被遮挡的解决办法 及 tinymce打开弹出菜单后直接关闭对话组件,导致该弹出菜单残留
19 6