Vue2和Vue3的区别

ops/2024/12/26 18:38:57/

响应式系统

Vue 2
  • 技术基础:使用 Object.defineProperty 实现响应式。
  • 局限性
    • 无法监听新增属性:如果在创建实例后添加新属性,这些属性不会自动成为响应式的。
    • 数组变更检测问题:直接通过索引设置值或长度不会触发更新。

示例:Vue 2 中的响应式数据

// Vue 2 示例
new Vue({data() {return {message: 'Hello, Vue 2!',items: []};},methods: {addItem() {// 直接修改数组不会触发视图更新this.items[0] = 'New Item';// 正确的做法是使用 Vue.set 或 this.$setthis.$set(this.items, 1, 'Another Item');}}
});
Vue 3
  • 技术基础:基于 ES6 Proxy 的全新响应式系统。
  • 优势
    • 全面监听:可以拦截对象的所有操作,包括属性的添加、删除、访问和修改。
    • 深层嵌套对象:对深层嵌套的对象也能自动追踪变化。

示例:Vue 3 中的响应式数据

// Vue 3 示例
import { reactive } from 'vue';const state = reactive({message: 'Hello, Vue 3!',items: []
});state.items.push('New Item'); // 自动触发视图更新
state.items[0] = 'Updated Item'; // 自动触发视图更新

组合式 API (Composition API)

Vue 2
  • 逻辑复用:依赖于混入(mixins),容易导致命名冲突和维护困难。
Vue 3
  • 逻辑复用:引入了 Composition API,允许开发者将相关逻辑封装到函数中,并在不同的组件之间共享。

示例:组合式 API 使用

// 定义一个可重用的逻辑钩子
import { ref, onMounted } from 'vue';function useMousePosition() {const x = ref(0);const y = ref(0);function update(event) {x.value = event.pageX;y.value = event.pageY;}onMounted(() => window.addEventListener('mousemove', update));return { x, y };
}// 在组件中使用
export default {setup() {const { x, y } = useMousePosition();return {x,y};}
};

生命周期钩子

Vue 2
  • 钩子名称:提供了明确的生命周期钩子,如 beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestroy, 和 destroyed
Vue 3
  • 钩子调整:保留了大部分原有的钩子,但为了统一命名规则,做了如下更改:
    • beforeDestroy 改为 beforeUnmount
    • destroyed 改为 unmounted
  • setup() 钩子:这是一个新的组件选项,运行在实例创建之前。

示例:Vue 3 中使用生命周期钩子

import { onMounted, onUnmounted } from 'vue';export default {setup() {onMounted(() => {console.log('Component is mounted');});onUnmounted(() => {console.log('Component is unmounted');});return {};}
};

模板支持与渲染函数

Vue 2
  • 根节点限制:模板必须有一个单一的根元素。
Vue 3
  • 片段支持:移除了单个根节点的要求,允许模板中有多个顶级元素。

示例:Vue 3 中的多根节点模板

<template><h1>Title</h1><p>Paragraph</p>
</template>

性能提升

Vue 2
  • 虚拟 DOM:尽管已经很高效,但在大规模应用中仍可能遇到性能瓶颈。
Vue 3
  • 改进的虚拟 DOM:重新设计的虚拟 DOM 实现,采用了更高效的算法来比较和更新 DOM 树。

示例:Vue 3 中的性能优化

虽然性能优化更多体现在框架内部,但从开发者的角度来看,减少不必要的计算和渲染可以帮助提高性能。例如,使用 computed 属性而不是方法来缓存计算结果:

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

TypeScript 支持

Vue 2
  • 类型支持:虽然可以结合 TypeScript 使用,但不是从一开始就设计好的。
Vue 3
  • 全面支持:核心库完全用 TypeScript 编写,提供了强大的类型定义和支持。

示例:Vue 3 中使用 TypeScript

import { defineComponent, ref } from 'vue';export default defineComponent({name: 'MyComponent',props: {msg: {type: String as PropType<string>,required: true}},setup(props) {const count = ref<number>(0);return {count,increment: () => count.value++};}
});

包大小

Vue 2
  • 体积问题:随着功能的增加,Vue 2 的核心库体积也在增大。
Vue 3
  • 模块化设计:通过 tree-shaking 技术,Vue 3 能够只打包实际使用的代码,显著减小了最终打包文件的体积。

示例:Vue 3 中的按需加载

// 只导入需要的部分
import { createApp, ref } from 'vue';

组件注册与全局配置

Vue 2
  • 组件注册:可以使用 Vue.component 注册全局组件,或者在单文件组件中通过 components 选项注册局部组件。
  • 全局配置:如全局事件总线、全局过滤器等,通常通过 Vue.prototype 或者 Vue.mixin 实现。
Vue 3
  • 组件注册:推荐使用 app.component 来注册全局组件,局部组件仍然可以通过 components 选项注册。
  • 全局配置:不再推荐使用 Vue.prototype 或 Vue.mixin,而是提供了新的 API 如 app.config.globalProperties 和 provide/inject 来实现类似功能。

示例:Vue 3 中的全局属性

import { createApp } from 'vue';
import App from './App.vue';const app = createApp(App);// 添加全局属性或方法
app.config.globalProperties.$globalMethod = () => {console.log('This is a global method');
};app.mount('#app');

插件系统

Vue 2
  • 插件安装:通过 Vue.use(plugin) 安装插件,插件可以添加全局组件、指令、混入等。
Vue 3
  • 插件安装:依然使用 app.use(plugin) 安装插件,但插件的设计更加模块化,鼓励按需加载和更细粒度的功能分割。

示例:Vue 3 中的插件

// 插件定义
export default {install(app, options) {// 添加一个全局方法app.config.globalProperties.$myPluginMethod = function() {console.log('Plugin method called');};// 添加一个全局指令app.directive('focus', {mounted(el) {el.focus();}});}
};// 使用插件
import myPlugin from './plugins/myPlugin';const app = createApp(App);
app.use(myPlugin);
app.mount('#app');

指令系统

Vue 2
  • 自定义指令:通过 Vue.directive 或者在组件内部使用 directives 选项来定义自定义指令。
Vue 3
  • 自定义指令:仍然支持自定义指令,但 API 略有变化,现在是通过 app.directive 来定义。此外,钩子函数的名称也做了调整(例如,bind 改为 mounted)。

示例:Vue 3 中的自定义指令

import { createApp } from 'vue';const app = createApp({});app.directive('colorize', {mounted(el, binding) {el.style.color = binding.value || 'red'; // 默认颜色为红色}
});app.mount('#app');// 在模板中使用
<template><p v-colorize="'blue'">这段文本应该是蓝色。</p>
</template>

自定义渲染器

Vue 2
  • 自定义渲染器:如果需要创建自定义渲染器(例如用于不同的 DOM 环境),则需要从头开始编写,这相对复杂。
Vue 3
  • 自定义渲染器:引入了 @vue/runtime-core 和 @vue/runtime-dom,使得创建自定义渲染器变得更加简单和模块化。开发者可以利用这些包提供的工具函数快速搭建适合特定环境的渲染逻辑。

示例:Vue 3 中的自定义渲染器

虽然这个例子较为复杂,但它展示了如何创建一个简单的自定义渲染器:

import { createRenderer } from '@vue/runtime-core';const renderer = createRenderer({createElement(type) {return document.createElement(type);},patchProp(el, key, prevValue, nextValue) {if (key.startsWith('on')) {const event = key.slice(2).toLowerCase();el.addEventListener(event, nextValue);} else {if (nextValue == null) {el.removeAttribute(key);} else {el.setAttribute(key, nextValue);}}},insert(child, parent, anchor = null) {parent.insertBefore(child, anchor);},remove(child) {const parent = child.parentNode;if (parent) {parent.removeChild(child);}},setElementText(node, text) {node.textContent = text;}
});renderer.createApp(App).mount(document.querySelector('#app'));

响应式数据类型

Vue 2
  • 响应式数据类型:仅限于对象和数组。
Vue 3
  • 响应式数据类型:除了对象和数组外,还支持原始类型的响应式包装(如 ref 和 reactive)。这允许对基本类型(如数字、字符串)进行响应式处理。

示例:Vue 3 中的 refreactive

import { ref, reactive } from 'vue';// 使用 ref 包装基本类型
const count = ref(0);// 使用 reactive 包装对象
const state = reactive({message: 'Hello, Vue!',items: []
});// 更新响应式数据
count.value++;
state.items.push('New Item');

错误处理与调试

Vue 2
  • 错误处理:主要依赖于开发者手动捕获错误并在代码中处理,Vue Devtools 提供了一些基本的帮助。
Vue 3
  • 错误处理:增强了内置的错误处理机制,提供了更友好的错误捕获和报告方式。同时,Vue Devtools 也得到了显著改进,增加了更多调试选项,如时间旅行调试、性能分析等。

示例:Vue 3 中的错误处理

import { createApp } from 'vue';const app = createApp(App);// 设置全局错误处理器
app.config.errorHandler = (err, vm, info) => {console.error(`Error in ${info}: ${err.message}`);
};app.mount('#app');

 插槽(Slots)

Vue 2
  • 语法多样:既有具名插槽也有作用域插槽,存在多种语法形式。
Vue 3
  • 统一语法v-slot 成为了指定作用域插槽的唯一方式。

示例:Vue 3 中的作用域插槽

<!-- 父组件 -->
<template><child-component v-slot="slotProps">{{ slotProps.message }}</child-component>
</template><!-- 子组件 -->
<template><slot :message="msg"></slot>
</template><script>
export default {data() {return {msg: 'Hello from child'};}
};
</script>

新增功能

Vue 3
  • Teleport:用于解决弹出层等场景下的 DOM 结构问题。
  • Suspense:用于等待异步依赖加载完成。

示例:使用 Teleport 和 Suspense

<!-- 使用 Teleport 将内容移动到 body -->
<template><teleport to="body"><div id="modal">Modal content</div></teleport>
</template><script>
import { defineAsyncComponent } from 'vue';export default {components: {AsyncComponent: defineAsyncComponent(() => import('./components/AsyncComponent.vue'))}
};
</script><!-- 使用 Suspense 等待异步组件加载 -->
<template><suspense><template #default><async-component /></template><template #fallback><div>Loading...</div></template></suspense>
</template>

移除的功能

Vue 3
  • .native 修饰符:移除,现在可以直接在自定义组件上监听原生事件。
  • keyCode 事件修饰符:移除,推荐使用键盘事件对象进行键码判断。
  • 过滤器:移除,鼓励使用计算属性或其他替代方案。

示例:Vue 3 中处理键盘事件

<template><input @keyup.enter="submitForm" />
</template><script>
export default {methods: {submitForm(event) {if (event.key === 'Enter') {// 处理表单提交逻辑}}}
};
</script>

其他改进

Vue 3
  • 调试工具:Vue Devtools 得到了增强,提供了更多调试选项。
  • SSR 支持:改善了服务器端渲染的支持。
  • 错误处理:提供了更友好的错误捕获和报告机制。

示例:Vue 3 中的全局错误处理

import { createApp } from 'vue';const app = createApp(App);app.config.errorHandler = (err, vm, info) => {// 处理错误console.error(`Error in ${info}: ${err.message}`);
};app.mount('#app');

http://www.ppmy.cn/ops/139322.html

相关文章

【计算机网络】实验9: 路由信息协议RIP

实验9 路由信息协议RIP 一、实验目的 本实验的主要目的是深入理解RIP&#xff08;路由信息协议&#xff09;的工作原理&#xff0c;以便掌握其在网络中的应用。通过对RIP的学习&#xff0c;我们将探讨该协议如何实现路由选择和信息传播&#xff0c;从而确保数据包能够在网络中…

创建的空 OpenCV 安卓应用程序以支持摄像头

在本节中&#xff0c;我们将扩展上一节中创建的空 OpenCV 应用程序以支持摄像头。我们将获取摄像头帧并将其显示在屏幕上。 告诉系统我们需要相机权限。将以下代码添加到文件MyApplication/app/src/main/AndroidManifest.xml&#xff1a; <uses-permission android:name&qu…

40分钟学 Go 语言高并发:服务性能调优实战

服务性能调优实战 一、性能优化实战概述 优化阶段主要内容关键指标重要程度瓶颈定位收集性能指标&#xff0c;确定瓶颈位置CPU、内存、延迟、吞吐量⭐⭐⭐⭐⭐代码优化优化算法、并发、内存使用代码执行时间、内存分配⭐⭐⭐⭐⭐系统调优调整系统参数、资源配置系统资源利用率…

Leecode经典题4--查找数组中的多数元素+Boyer-Moore 投票算法

题目描述&#xff1a; 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 输入输出示例 输入&#xff1a;nums [2,2,1,1,1,2,2] 输出…

关于linux 下的中断

1. /proc/irq/<irq_number>/ 下属性详解 在 Linux 系统中&#xff0c;每个中断号&#xff08;IRQ&#xff09;都有一个对应的目录 /proc/irq/<irq_number>/&#xff0c;包含与该中断相关的属性文件。这些文件用于查看和配置中断的具体行为。 以下是 /proc/irq/&l…

Qt Designer Ui设计 功能增加

效果展示 输入密码&#xff0c;密码错误&#xff0c;弹出提示 密码正确&#xff0c;弹出提示并且关闭原窗口 代码&#xff08;只提供重要关键主代码&#xff09;lxh_log.py代码&#xff1a; import sysfrom PySide6.QtWidgets import QApplication, QWidget, QPushButtonfrom …

安装更新upgrade导致ubuntu崩溃

安装更新导致ubuntu崩溃 前言uuid编不过&#xff0c;导致的崩溃 记录一些ubuntu崩溃的过程。 目前只有一个&#xff0c;以后遇到都放在这里&#xff0c;以提醒自己。 前言 如果从10000年看现在的linux&#xff0c;不是说不完美&#xff0c;而是糟透了。 linux的版本号&#xf…

【人工智能-科普】图神经网络(GNN):与传统神经网络的区别与优势

文章目录 图神经网络(GNN):与传统神经网络的区别与优势什么是图神经网络?图的基本概念GNN的工作原理GNN与传统神经网络的不同1. 数据结构的不同2. 信息传递方式的不同3. 模型的可扩展性4. 局部与全局信息的结合GNN的应用领域总结图神经网络(GNN):与传统神经网络的区别与…