Vue3和Vue2的区别

前言

Vue 3的文章也跟新了不少,相比vue2还是有很多区别的,有许多重要的变化和改进。以下是 Vue 3 相对于 Vue 2 的一些主要区别:

生命周期函数

生命周期函数基本和vue2差不多,名字前加了on
具体如下:

  1. onBeforeMount 在挂载开始之前被调用。
  2. onMounted 挂载完成后被调用。
  3. onBeforeUpdate 数据更新前调用。
  4. onUpdated 数据更新后调用。
  5. onBeforeUnmount 在卸载之前被调用,此时组件仍然是可用的。
  6. onUnmounted 在卸载后被调用,此时组件已经不再可用。

由于引入了 Composition API,组件的逻辑可以通过 setup 函数来定义。setup 函数中的代码会在 beforeCreate 和 created 钩子之前执行。这意味着在 setup 函数中可以执行之前在 beforeCreate 和 created 钩子中执行的逻辑,所以还是能使用beforeCreatecreated

// vue3
<script setup>     
import { onMounted } from 'vue';   // 使用前需引入生命周期钩子onMounted(() => {// ...
});onMounted(() => {// ...
});
</script>
</script> 

新增的 Vue 3 生命周期钩子:

  1. onBeforeRender 在渲染开始之前调用,此时组件的状态和属性已经被解析,但尚未生成虚拟 DOM。
  2. onRender 在渲染函数被调用时调用,返回一个虚拟 DOM 树。
  3. onBeforeUpdate 数据更新前调用,与 Vue 2 的 beforeUpdate 不同,Vue 3 的 onBeforeUpdate 可以接收一个回调函数,用于在数据更新前执行异步操作。

响应式原理

Vue 3 和 Vue 2 在响应式原理上有一些重要的区别,尽管它们的核心思想都是基于数据劫持实现的,但 Vue 3 引入了 Proxy 对象作为数据劫持的主要手段,而 Vue 2 使用的是 Object.defineProperty,无法监听对象或数组新增、删除的元素。

Vue 3 的响应式原理:

  1. Proxy 对象:

    • Vue 3 使用了 JavaScript 的 Proxy 对象来实现响应式。Proxy 提供了更灵活且强大的拦截器,可以捕捉更多的操作,包括对象属性的读取、写入、删除等。
  2. Reactive 函数:

    • 在 Vue 3 中,通过 reactive 函数将一个普通对象转换为响应式对象。这个函数会使用 Proxy 对象来包装原始对象,实现对对象属性的代理。
    import { reactive } from 'vue';const state = reactive({ count: 0 });
    
  3. Ref 函数:

    • Vue 3 引入了 ref 函数,用于创建一个包含响应式数据的引用对象。这个函数返回一个具有 .value 属性的对象,通过对这个对象进行访问和修改来触发响应式更新。
    import { ref } from 'vue';const count = ref(0);
    

Vue 2 的响应式原理:

  1. Object.defineProperty:

    • Vue 2 使用 Object.defineProperty 来劫持对象的属性,通过在对象属性的读取和写入时触发 getter 和 setter 函数来实现响应式。
  2. Observer 类:

    • 在 Vue 2 中,一个被观察的对象会被转化为 Observer 类的实例,Observer 类会递归地为对象的每个属性创建 getter 和 setter。
  3. getter 和 setter:

    • 在 Vue 2 中,当访问或修改对象的属性时,通过 getter 和 setter 来触发依赖的收集和更新。
    // 伪代码,用于说明 Vue 2 的响应式原理
    function defineReactive(obj, key, val) {Object.defineProperty(obj, key, {get() {// 收集依赖// ...return val;},set(newVal) {// 更新视图// ...val = newVal;}});
    }
    

Composition API

Vue 3 中的 Composition API 是一种新的组织组件逻辑的方式,它提供了更灵活和强大的工具来组织和重用组件代码。Composition API 的引入使得代码更易于理解、维护,同时也更好地支持 TypeScript。以下是 Composition API 的一些核心概念和特性:

1. setup 函数:

  • Composition API 中的组件逻辑主要集中在 setup 函数中。这个函数在组件实例创建之前调用,它接收 propscontext 参数,允许你在组件创建之前进行一些初始化工作。
setup(props, context) {// 在这里可以进行组件初始化工作// 可以访问 props 和 context 对象
}

2. Reactive 和 Ref:

  • Composition API 提供了 reactiveref 函数来创建响应式的数据。reactive 用于创建包含响应式对象,而 ref 用于创建包含基本类型值的引用对象。
import { reactive, ref } from 'vue';setup() {const state = reactive({ count: 0 });const count = ref(0);return { state, count };
}

3. Watch 和 WatchEffect:

  • Composition API 提供了 watchwatchEffect 函数来进行数据的监听。watchEffect 在其依赖的响应式数据变化时会自动运行,而 watch 则更加灵活,可以监听特定的数据变化,并执行相应的操作。
import { watch, watchEffect } from 'vue';setup() {const state = reactive({ count: 0 });watchEffect(() => {console.log(state.count);});watch(() => state.count, (newValue, oldValue) => {console.log(`count 从 ${oldValue} 变为 ${newValue}`);});
}

4. Lifecycle Hooks:

  • Composition API 改变了生命周期钩子的写法,不再使用以前的 Options API 的方式,而是使用 onXxx 的形式。例如,created 钩子变为 onCreated
setup() {onMounted(() => {// 组件挂载后执行的逻辑});onUpdated(() => {// 组件更新后执行的逻辑});onUnmounted(() => {// 组件卸载前执行的逻辑});
}

5. Provide 和 Inject:

  • Composition API 中提供了 provideinject 函数,用于父子组件之间的传值。这使得跨组件之间的状态管理更加灵活。
// 父组件
setup() {const data = reactive({ message: 'Hello from parent' });provide('data', data);
}// 子组件
setup() {const data = inject('data');console.log(data.message); // 输出 'Hello from parent'
}

6. Refs 和 Reactive:

  • Composition API 中的 refreactive 返回的对象在模板中的使用方式变得更加直接,不再需要 .value
// 在模板中
<template><p>{{ count }}</p>
</template>// 在 setup 函数中
setup() {const count = ref(0);return { count };
}

7. Custom Hooks:

  • Composition API 允许开发者创建自定义的逻辑复用函数,称为 Custom Hooks。这使得逻辑的重用变得更加方便。
// Custom Hook
export function useCounter() {const count = ref(0);function increment() {count.value++;}return { count, increment };
}// 在组件中使用
setup() {const { count, increment } = useCounter();return { count, increment };
}

Composition API 引入了这些新的概念和工具,使得组件的逻辑可以更清晰、更可组织,同时也提高了代码的可维护性。它并不是要取代 Options API,而是提供了另一种更灵活的选择。开发者可以根据项目的需要选择使用 Options API 还是 Composition API。

Teleport

Teleport 是 Vue 3 中的一个新特性,它允许你在组件树中的任何位置渲染元素,使得在 DOM 中的位置可以脱离组件的父子关系。这对于创建全局弹窗、模态框或者在组件外渲染一些内容非常有用。Teleport 的核心思想是将要渲染的内容传送(teleport)到另一个位置。

基本用法:

<template><div><button @click="showModal = true">Show Modal</button><teleport to="body"><Modal v-if="showModal" @close="showModal = false"><!-- Modal 内容 --></Modal></teleport></div>
</template><script>
import { ref } from 'vue';export default {data() {return {showModal: false};}
};
</script>

在上面的例子中,<Modal> 组件的内容被传送到 <teleport to="body"> 下,也就是挂载到了 body 元素下。这样 Modal 就可以在 DOM 结构中脱离当前组件的位置,使得其可以在整个页面中显示,而不受到组件嵌套的限制。

Teleport 的属性:

  • to: 指定要传送到的目标位置,可以是一个 CSS 选择器字符串、DOM 元素或者一个函数。

    <teleport :to="document.getElementById('target')"><!-- 要传送的内容 -->
    </teleport>
    
  • disabled: 一个布尔值,用于控制是否启用 Teleport。当为 true 时,Teleport 将不会生效,传送的内容将在组件的父级中渲染。

    <teleport :to="document.getElementById('target')" :disabled="shouldDisable"><!-- 要传送的内容 -->
    </teleport>
    

注意事项:

  1. 目标元素的存在性: 在使用 Teleport 时,要确保传送目标存在于 DOM 中。如果目标不存在,Vue 会在控制台给出警告。

  2. Scoped CSS: Teleport 不会破坏 Vue 的样式封装,传送的内容仍然受到组件的样式作用域限制。

  3. 事件和过渡: 传送的内容中的事件和过渡仍然可以正常工作,不受 Teleport 影响。

  4. 性能考虑: Teleport 的使用应当根据具体情况来考虑性能影响。在某些情况下,可能因为跨越组件边界,导致性能损失。因此,在考虑使用 Teleport 时,建议先进行性能测试。

Suspense 和异步组件

Vue3 提供 Suspense 组件,在等待异步组件加载完成前渲染默认的内容,如 loading ,使用户的体验更平滑。使用它,需在模板中声明,并包括两个命名插槽:default 和 fallback。Suspense 确保加载完异步内容时显示默认插槽,并将 fallback 插槽用作加载状态。

<template><Suspense><template #default><AsyncComponent /><AsyncData /></template><template #fallback><div>Loading...</div></template></Suspense>
</template><script setup>
const AsyncComponent = () => import('./AsyncComponent.vue');
const AsyncData = () => fetchData(); // 异步数据获取函数
</script>

Fragments

在vue2中,必须有个根元素包裹组件,不然会运行报错。Vue 3 支持 Fragments,即可以在模板中使用多个根元素而不需要包裹它们在一个父元素中。

Tree-shaking

Tree-shaking 是一种用于剔除未使用代码(dead code)的优化技术,它通过静态分析的方式识别和移除项目中未被引用的模块或代码片段,以减小最终打包体积。Vue 3 被设计为更易于 Tree-shaking,以下是一些关于如何使用 Vue 3 进行 Tree-shaking 的注意事项:

  1. 按需引入模块:
    Vue 3 的模块是按需引入的,这意味着你只需要引入你实际使用的模块,而不是整个库。例如,如果你只使用了 reactive 函数,只需引入该函数:

javascript
Copy code
import { reactive } from ‘vue’;
这样可以避免引入整个 Vue 3 库,减小了打包体积。

  1. 使用 Composition API:
    Vue 3 的 Composition API 提供了更灵活的组织组件逻辑的方式。由于 Composition API 是按需引入的,你只需要引入你实际使用的功能函数,而不是整个 API:

javascript
Copy code
import { ref, onMounted } from ‘vue’;

export default {
setup() {
const count = ref(0);

onMounted(() => {console.log('Component is mounted');
});return { count };

}
};
3. 单文件组件的优化:
在单文件组件中,确保只导入你需要的组件和样式,以避免引入整个文件。同时,避免在模板中使用未使用的组件,因为这也可能影响 Tree-shaking 的效果。

  1. 懒加载和异步组件:
    使用懒加载和异步组件可以帮助实现按需加载,仅在需要的时候才加载相关代码。这对于 Tree-shaking 是非常有利的。

  2. 优化生产构建:
    在生产环境中,确保你的构建工具和配置是针对生产环境进行了优化的。例如,使用生产模式构建、开启压缩、移除调试信息等。

  3. 检查打包结果:
    可以通过检查最终打包结果,查看是否成功剔除了未使用的代码。你可以使用工具或者分析打包后的代码,以确保 Tree-shaking 的效果符合预期。

使用这些方法,结合正确的配置和构建工具,可以使 Vue 3 更好地支持 Tree-shaking,帮助你减小项目的最终打包体积。

Diff算法的优化

Vue 3 在 Virtual DOM 的 diff 算法上进行了一系列的优化,主要目标是提高更新性能、减少不必要的操作、以及更好地利用现代浏览器的特性。以下是一些 Vue 3 中 Virtual DOM diff 算法的优化:

  1. 静态树提升:

Vue 3 引入了静态树提升,通过标记静态节点,可以在渲染时跳过对这些节点的处理,减少了 Virtual DOM 的操作和对比。这使得在一些场景下,特别是对于大型列表或者频繁更新的组件,能够提高性能。

  1. 源码生成优化:

Vue 3 利用了编译器生成的源码的优势。在运行时,不再需要对模板进行解析,而是直接使用生成的 JavaScript 代码进行渲染。这样避免了一些不必要的运行时开销,提高了渲染性能。

  1. Cache Handlers:

Vue 3 中使用了缓存处理器(cache handlers)来缓存动态组件和事件处理器。这样在多次渲染中,如果组件和事件处理器没有发生变化,可以直接复用之前的结果,减少了重复计算的开销。

  1. 事件侦听器的优化:

Vue 3 在处理事件侦听器时引入了更高效的机制。在处理相同事件的不同侦听器时,Vue 3 会尽量合并它们,以减少事件绑定和解绑时的性能开销。

  1. Patch Flag:

Vue 3 引入了 patch flag 的概念,用于快速判断两个节点是否相同,从而避免不必要的深度对比。Patch flag 会记录节点的特定信息,例如节点的类型、属性、子节点等,以帮助更快速地进行比较。

6. Fragments 和合并的 Slot 虚拟节点:

Vue 3 支持 Fragments,使得组件的模板中可以有多个根节点。这样在渲染时就不需要额外的根节点包裹,减少了 Virtual DOM 的节点数量。对于一些 slot 的合并也进行了优化,减少了 Virtual DOM 的操作。

7. Block Tree Walking:

Vue 3 引入了块级树遍历(Block Tree Walking)的概念,对于动态组件和模板的动态块,Vue 3 能够更高效地处理。

更好的 TypeScript 支持

Vue 3 对 TypeScript 提供了更好的支持,它的代码库和构建工具都是用 TypeScript 编写的,同时也提供了一些特性来优化 TypeScript 开发体验。
自定义模板块的 TypeScript 支持:Vue 3 中对于使用自定义模板块的 TypeScript 支持更加友好,例如对于 defineProps、defineEmits 等。

v-model

在 Vue 3 中,v-model 的使用方式相对于 Vue 2 有一些变化,主要是为了提供更灵活的用法和更好的支持。

1. v-model 的参数化:

在 Vue 3 中,v-model 可以接收参数,可以自定义 prop 和 event 的名称。这使得 v-model 在组件内的用法更加灵活,不再限定于默认的 modelValueupdate:modelValue

<template><MyComponent v-model:customProp="value" />
</template><script>
import { ref } from 'vue';export default {setup() {const value = ref('');return { value };}
};
</script>

在上面的例子中,v-model 使用了 :customProp,这样在 MyComponent 内部会使用 customProp 作为 prop 名称和 update:customProp 作为事件名称。

2. v-model 的修饰符支持:

Vue 3 引入了修饰符 API,这使得你可以在 v-model 上使用修饰符,例如 .lazy.trim

<template><input v-model.lazy="value" />
</template><script>
import { ref } from 'vue';export default {setup() {const value = ref('');return { value };}
};
</script>

在上面的例子中,.lazy 修饰符表示在 inputchange 事件之后更新数据,而不是在 inputinput 事件触发时即时更新数据。

3. v-model 在自定义组件上的使用:

在 Vue 3 中,自定义组件上的 v-model 更加灵活。你可以通过 model 选项自定义 prop 和 event 的名称。

<template><MyComponent v-model:customProp="value" />
</template><script>
import { ref } from 'vue';export default {props: {customProp: String},emits: ['update:customProp'],setup(props) {const value = ref('');return {value,// 通过手动触发事件来更新父组件的数据updateValue(newValue) {props['update:customProp'](newValue);}};}
};
</script>

小结

Vue 3 在性能、可维护性、功能和 TypeScript 支持等方面都有很多的提升,但也需要开发者适应一些新的概念和 API。如果要升级到 Vue 3,建议查看官方迁移指南。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用npm失败解决方案

npm config rm proxy npm config rm https-proxy

MongoDB 定位 oplog 必须全表扫描吗?

MongoDB oplog &#xff08;类似于 MySQL binlog&#xff09; 记录数据库的所有修改操作&#xff0c;除了用于主备同步&#xff1b;oplog 还能玩出很多花样&#xff0c;比如 全量备份 增量备份所有的 oplog&#xff0c;就能实现 MongoDB 恢复到任意时间点的功能通过 oplog&am…

JavaScript-方法

方法的定义 方法就是把函数放在对象里面 var wang {name: 网络,birth: 2020,// 方法age: function () {// 今年 - 出生的年var now_year new Date().getFullYear();return now_year-this.birth} } // 属性 wang.name // 方法&#xff0c;一定要带() kuangshen.age()拆开上面…

Python程序员30行代码素描表白!网友:花里胡哨

总有人说程序员不够浪漫&#xff01;其实我们只是没时间而已&#xff0c;等我们有时间了&#xff0c;还有普通人什么事儿&#xff1f;最近就有一个小伙伴上热搜了&#xff01;原来他用Python给可爱的女朋友画了一幅素描&#xff01;不到30行代码&#xff0c;一起来学学给她一个…

解读NoSQL最新现状和趋势:云NoSQL数据库将成重要增长引擎

NoSQL最早起源于1998年&#xff0c;但从2009年开始&#xff0c;NoSQL真正开始逐渐兴起和发展。回望历史应该说NoSQL数据库的兴起&#xff0c;完全是十年来伴随互联网技术&#xff0c;大数据数据的兴起和发展&#xff0c;NoSQL在面临大数据场景下相对于关系型数据库运用&#xf…

使用EMR-Kafka Connect进行数据迁移

1.背景 流式处理中经常会遇到Kafka与其他系统进行数据同步或者Kafka集群间数据迁移的情景。使用EMR Kafka Connect可以方便快速的实现数据同步或者数据迁移。 Kafka Connect是一种可扩展的、可靠的&#xff0c;用于在Kafka和其他系统之间快速地进行流式数据传输的工具。例如可…

亚信安全发布“安全定义边界”2020发展理念 赋能企业在5G时代的数字化安全运营能力

2020年4月21日&#xff0c;以“信行合一 聚势致远”为主题的亚信安全2020合作伙伴大会正式在云端拉开帷幕&#xff0c;超过1500家生态伙伴相聚云端&#xff0c;在为期3天的大会上共话安全&#xff0c;共商发展。会上&#xff0c;亚信安全正式发布“安全定义边界”2020发展理念&…

JavaScript-Date日期对象

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <script>const now new Date(); // Tue Aug 10 2021 15:32:27 GMT0800 (中国标准时间)now.g…

如何实现input输入框自带清除按钮

最近&#xff0c;项目中需要&#xff0c;在输入框获取焦点是动态显示“”图标。即在输入框中输入内容时&#xff0c;右边显示“”按钮&#xff1b;输入框为空时&#xff0c;“”按钮消失。难点在于获取焦点的同时&#xff0c;获取输入内容。 注意&#xff1a;本例子的样式基于…

独家专访阿里集团副总裁贾扬清:我为什么选择加入阿里巴巴?

真正跟贾扬清近距离接触后笔者发现&#xff0c;这位被很多人称为“AI 架构大神”的 80 后青年科学家&#xff0c;更像一位温柔且平易近人的邻家“学霸”&#xff0c;虽然技能全面碾压但丝毫没有架子。加入阿里以来&#xff0c;贾扬清一直忙于了解集团覆盖范围极广的各项产品和业…

python-解码 decode 报错的问题

当解码使用默认的 decode() 拨错时&#xff0c;可以设置 errors 参数的值来解决 print(line) line_de_replace line.decode(errorsreplace).strip() # 用&#xff1f;代替 print("line_de_replace:", line_de_replace) line_de_ignore line.decode(errorsignore)…

layui Form内容重置清空

layer.open({type: 1,anim: -1,title: 添加单位,closeBtn: 1,offset: r,// shade: 0.1,shadeClose: true,skin: layui-anim layui-anim-rl layui-layer-adminRight,content: $(#innerBox),area: [500px, 90%],btn: [确定, 取消],success: function(layero, index) {// 重置清空…

字节码技术在模块依赖分析中的应用

背景 近年来&#xff0c;随着手机业务的快速发展&#xff0c;为满足手机端用户诉求和业务功能的迅速增长&#xff0c;移动端的技术架构也从单一的大工程应用&#xff0c;逐步向模块化、组件化方向发展。以高德地图为例&#xff0c;Android 端的代码已突破百万行级别&#xff0…

华为发布基于自进化AI的HiSec Insight安全态势感知系统

2020年4月21日&#xff0c;华为举办“安全新视界&#xff0c;AI知未然”主题线上发布会&#xff0c;邀请第三方研究机构、行业客户和合作伙伴共同探讨安全态势感知系统的演进方向&#xff0c;并见证华为HiSec Insight安全态势感知系统的全新面世。华为HiSec Insight安全态势感知…

“做好大数据测试,我是认真的!”

阿里妹导读&#xff1a;大数据已然是当下的重要课题&#xff0c;大大小小的企业在重视大数据的同时&#xff0c;也渐渐重视大数据质量的问题。阿里巴巴测试开发专家小郅&#xff0c;今天会分享他对数据测试的系统性思考。文章内容架构清晰&#xff0c;内容较长&#xff0c;建议…

JavaScript-面向对象原型继承

let user {name: "wang",age: 3,run: function () {console.log(this.name " run ......");} };let bob {name: "bob" };// bob 的 原型是 user bob.__proto__ userbob.run() // bob run ...... console.log(bob.age) // 3 console.log(bo…

从安全到镜像流水线,Docker 最佳实践与反模式一览

作者 | Timothy Mugayi译者 | 弯月&#xff0c;责编 | 夕颜封图 | CSDN付费下载自视觉中国出品 | CSDN&#xff08;ID:CSDNnews&#xff09;在使用Docker的大部分时间里&#xff0c;我们并不关心其内部的工作原理。仅凭启动一个Docker容器并且让应用程序运行良好&#xff0c;并…

ChaosBlade 发布对 C++ 应用混沌实验的支持

前言 为满足 C 应用系统故障演练&#xff0c;阿里妈妈安全生产团队开源了 C 混沌实验执行器&#xff0c;填补了 C 应用混沌工程实验的空白&#xff0c;其遵循《混沌实验模型》&#xff0c;可通过 ChaosBlade 工具直接执行。项目详情点击这里&#xff01; 。 本文重点介绍该执…

TortoiseGitPlink提示输入密码解决方法

文章目录一、现象二 、解决方法2.1. 打开TortoiseGit 下的puttygen工具2.2. 点击load&#xff0c;加载私钥2.3. 生成一个新的私钥2.4. 项目拉取2.5. 配置新的私钥一、现象 二 、解决方法 2.1. 打开TortoiseGit 下的puttygen工具 双击D:\software\TortoiseGit\bin下面的puttyg…

引领高并发直播场景进入毫秒时代,阿里云发布超低延时直播服务

近日&#xff0c;阿里云上线超低延时直播服务RTS&#xff08;Real-time Streaming&#xff09;&#xff0c;该服务在视频直播产品的基础上&#xff0c;进行全链路延时监控、传输协议改造等底层技术优化&#xff0c;支持千万级并发场景下的毫秒级延迟直播能力&#xff0c;保障低…