记一次 Vue2 迁移 Vue3 的实践总结

大家好,我是若川。持续组织了6个月源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列

一、Vue3

Vue3中文文档[1]

  • Vue3是什么,与Vue2区别(What)

  1. Performance:性能更强。

  2. Tree shaking support:可以将无用模块“剪辑”,仅打包需要的。

  3. Composition API:组合式API

  4. Fragment, Teleport, Suspense:“碎片”,TeleportProtal传送门,“悬念”

  5. Better TypeScript support:更优秀的Ts支持

  6. Custom Renderer API:暴露了自定义渲染API

  • 为什么要大版本迭代 (Why)

  1. 主流浏览器对新的JavaScript语言特性的普遍支持。

  2. 当前Vue代码库随着时间的推移而暴露出来的设计和体系架构问题。

  • 他是如何提升的(How)

  1. 响应式系统提升: 使用Proxy提升了响应式的性能和功能

  2. 编译优化: 标记和提升所有的静态节点,diff时只需要对比动态节点内容

  3. 事件缓存: 提供了事件缓存对象cacheHandlers,无需重新创建函数直接调用缓存的事件回调

  4. 打包和体积优化: 按需引入,Tree shaking支持(ES Module)

二、编码

全局API

  1. 新增】createApp: 入口文件(main.ts)挂载方式

import { createApp } from "vue";import App from "./App.vue";// Vue2new Vue({render: (h) => h(App)}).$mount("#app");// Vue3createApp(App).use(**).mount("#app");
  1. 【修改】

2.x 全局 API3.x 实例 API (app)
Vue.configapp.config
Vue.config.productionTip
Vue.config.ignoredElementsapp.config.isCustomElement
Vue.componentapp.component
Vue.directiveapp.directive
Vue.mixinapp.mixin
Vue.useapp.use
Vue.prototypeapp.config.globalProperties

config.ignoredElements替换为config.isCustomElement

引入此配置选项的目的是支持原生自定义元素,因此重命名可以更好地传达它的功能,新选项还需要一个比旧的 string/RegExp 方法提供更多灵活性的函数:

// Vue2Vue.config.ignoredElements = [// 用一个 `RegExp` 忽略所有“ion-”开头的元素// 仅在 2.5+ 支持/^ion-/]// Vue3const app = Vue.createApp({})app.config.isCustomElement = tag => tag.startsWith('ion-')

Vue.prototype 替换为 config.globalProperties

在Vue 2中,Vue.prototype通常用于添加可在所有组件中访问的属性。

Vue 3中的等效项是config.globalProperties。在实例化应用程序内的组件时,将复制这些属性

// Vue2Vue.prototype.$http = () => {}// Vue3const app = Vue.createApp({})app.config.globalProperties.$http = () => {}

生命周期

2.0生命周期3.0生命周期
beforeCreate(组件创建之前)setup()
created(组件创建完成)setup()
beforeMount(组件挂载之前)onBeforeMount(组件挂载之前)
mounted(组件挂载完成)onMounted(组件挂载完成)
beforeUpdate(数据更新,虚拟DOM打补丁之前)onBeforeUpdate(数据更新,虚拟DOM打补丁之前)
updated(数据更新,虚拟DOM渲染完成)onUpdated(数据更新,虚拟DOM渲染完成)
beforeDestroy(组件销毁之前)onBeforeUnmount(组件销毁之前)
destroyed(组件销毁之后)onUnmounted(组件销毁之后)
activated(被 keep-alive 缓存的组件激活时调用)onActivated(被激活时执行)
deactivated(被 keep-alive 缓存的组件停用时调用)onDeactivated(比如从 A 组件,切换到 B 组件,A 组件消失时执行)
errorCaptured(当捕获一个来自子孙组件的错误时被调用)onErrorCaptured(当捕获一个来自子孙组件的异常时激活钩子函数)

新特性

  1. Options API => Composition API

2bd0bbfef0b153dbac77359962e78b1e.gifef8ac0c95101993c2f7519a9772d24a3.gif
  1. setup()

import {toRefs} from 'vue'export default {name: 'demo',props:{name: String,},// setup()作为在组件内使用Composition API的入口点。// 执行时机是在beforeCreate和created之间,不能使用this获取组件的其他变量,// 而且不能是异步。setup返回的对象和方法,都可以在模版中使用。setup(props, context){// 这里需要使用toRefs来进行解构// 这里的props与vue2基本一致,当然这里的name也可以直接在template中使用const { name }=toRefs(props);console.log(name.value);// context是一个上下文对象//【从原来 2.x 中 this 选择性地暴露了一些 property(attrs/emit/slots)】// 属性,同vue2的 $attrsconsole.log(context.attrs);// 插槽console.log(context.slots);// 事件,同vue2的 $emitconsole.log(context.emit);// 生命周期钩子onMounted(() => {})}}

注意点:

  • 注意 props 对象是响应式的,watchEffectwatch 会观察和响应 props 的更新,不要解构 props 对象,那样会使其失去响应性

  • attrsslots 都是内部组件实例上对应项的代理,可以确保在更新后仍然是最新值。所以可以解构,无需担心后面访问到过期的值

  • this setup()中不可用。由于 setup() 在解析 2.x 选项前被调用,setup() 中的 this 将与 2.x 选项中的 this 完全不同。同时在 setup() 和 2.x 选项中使用 this 时将造成混乱

  1. 响应式reactive,ref

import { ref, reactive, toRefs } from 'vue';setup() {// ref// ref 对我们的值创建了一个响应式引用const counter = ref(0); // reactive// 接收一个普通对象然后返回该普通对象的响应式代理const obj = {a:1};const objReactive = reactive(obj);const add = () => {counter.value++;objReactive.a++;}return {counter,  // return返回会自动解套【在模板中不需要.value】objReactive,add,}; // 这里返回的任何内容都可以用于组件的其余部分}


refreactive
入参基本类型引用类型
返回值响应式且可变的 ref 对象响应式代理(Proxy)
访问方式1.ref 对象拥有一个指向内部值的单一属性 .value
2.在dom和setup()的return中会自动解套
3.ref 作为 reactive 对象的 property 被访问或修改时,也将自动解套
直接.访问即可

问题 & 注意点: 因为reactive是组合函数【对象】,所以必须始终保持对这个所返回对象的引用以保持响应性,不能解构该对象或者展开

例如:

const { a } = objReactive或者return { ...objReactive }

解决方法:

toRefs API

用来提供解决此约束的办法——它将响应式对象的每个 property 都转成了相应的 ref【把对象转成了ref】。

import { reactive, toRefs } from 'vue';setup() {// reactive// 接收一个普通对象然后返回该普通对象的响应式代理const obj = {a:1};const objReactive = reactive(obj);// toRefs// 将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的refconst objRef = toRefs(objReactive);const { a } = objRef;const addObj = () => {a.value++;console.log(a.value, objRef, objReactive, obj);}return {...objRef,addObj}; }
  • Hooks方式

  1. counter.js

import { ref } from 'vue';export function useCounter() {const count = ref(0);const decrement = () => {count.value--;}const increment = () => {count.value++;}return {count,decrement,increment}}
  1. 父组件

<template><h2>{{ count }}</h2><button @click="increment">increment</button><button @click="decrement">decrement</button></template><script>import { useCounter } from './counter.js';export default {setup() {return {...useCounter(),};}}</script>

响应式计算和侦听

  1. computed

const count = ref(1)/*不支持修改【只读的】 */const plusOne = computed(() => count.value + 1)plusOne.value++ // 错误!/*【可更改的】 */const plusOne = computed({get: () => count.value + 1,set: (val) => {count.value = val - 1},})
  1. watch

// 直接侦听一个 refconst count = ref(0)watch(count, (count, prevCount) => {/* ... */})// 也可以使用数组来同时侦听多个源watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {/* ... */})
  1. watchEffect

  • 定义:在响应式地跟踪其依赖项时立即运行一个函数,并在更改依赖项时重新运行它

  • 第一个参数:effect,顾名思义,就是包含副作用的函数。如下代码中,副作用函数的作用是:当 count 被访问时,旋即(随即)在控制台打出日志。

  • 返回值:也是一个函数,显式调用可以清除watchEffect,组件卸载时会被隐式调用

const count = ref(0);const stop = watchEffect(() => console.log(count.value)); // -> logs 0setTimeout(() => {count.value++; // -> logs 1}, 100);// 清除watchEffectstop();
  • 清除副作用(onInvalidate)

watchEffect 的第一个参数——effect函数——自己也有参数:叫onInvalidate,也是一个函数,用于清除 effect 产生的副作用。

onInvalidate 被调用的时机很微妙:它只作用于异步函数,并且只有在如下两种情况下才会被调用:

  1. effect 函数被重新调用时

  2. 当监听器被注销时(如组件被卸载了)

import { asyncOperation } from "./asyncOperation";const id = ref(0);watchEffect((onInvalidate) => {const token = asyncOperation(id.value);// onInvalidate 会在 id 改变时或停止侦听时,取消之前的异步操作(asyncOperation)onInvalidate(() => {token.cancel();});});
  • 第二个参数:options

主要作用是指定调度器,即何时运行副作用函数。

// fire before component updateswatchEffect(() => {/* ... */},{flush: "pre",onTrigger(e) {// 依赖项变更导致副作用被触发时,被调用debugger;},onTrack(e) {// 依赖项变更会导致重新追踪依赖时,被调用【调用次数为被追踪的数量】debugger},});

三、源码

未完待续...

四、其他相关

Vite2.0,2月17号正式发布

中文文档:https://cn.vitejs.dev/

五、感悟

优点:很优秀

缺点:他的对手(React),更优秀

虽然好多地方神似React,但是我们也可以从中看出,他们的都源于比较成熟的编程范式——FP(Functional Programming)。

框架只是工具,解决问题才是终极目标;我们还是要把重点放在领悟框架的设计思想上;悟到了,才是真正掌握了解决问题的手段。(抄的)

参考文档:

https://juejin.cn/post/6858558735695937544#heading-0

https://blog.csdn.net/qq_34998786/article/details/113287653

https://www.jianshu.com/p/ad38a1f27d0f

https://juejin.cn/post/6844904134303301645

https://juejin.cn/post/6858558735695937544#heading-25

https://juejin.cn/post/6888925879243079687

https://www.jianshu.com/p/a8fdf52d0bcf

参考资料

[1]

Vue3中文文档: https://v3.cn.vuejs.org/

- END -

46cbbc2ff9fc5acae5ff4f2bbeb20ae3.gif

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经写了7篇,点击查看年度总结。
同时,最近组织了源码共读活动,帮助3000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。

83fef62422ca7764f77a8990243028c1.png

识别方二维码加我微信、拉你进源码共读

今日话题

略。分享、收藏、点赞、在看我的文章就是对我最大的支持~

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

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

相关文章

改错3-38

#include<iostream.h>class time{private:int hour,minute,second;public:void settime(int h,int m,int s) { hour(h>0&&h<24)?h:0; minute(m>0&&m<60)?m:0; second(s>0&&s<60)?s:0; }void sh…

魔兽怀旧网站模块下载_一个人的网站重新设计和怀旧

魔兽怀旧网站模块下载Despite how I look, I’m the kind kind of person that loves to play old video games. (Full disclosure: I look exactly like the kind of person that loves to play old video games).尽管我长得很帅&#xff0c;但我还是一个喜欢玩旧视频游戏的人…

Node.js 可以和 Web 实现 HTTP 请求的跨平台兼容了!

大家好&#xff0c;我是若川。持续组织了6个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列大家好…

zeplin加载 不出图片_为什么Zeplin不能解决您的所有问题

zeplin加载 不出图片Design handover involves communicating the visual styles and behaviours of your design so they can be translated into code.设计移交涉及传达设计的视觉样式和行为&#xff0c;以便可以将它们转换为代码。 Back in the Dark Ages of digital desig…

POJ 基础数学

数学 组合数学 POJ3252,poj1850,poj1019,poj1942 数论 poj2635, poj3292,poj1845,poj2115 计算方法&#xff08;二分&#xff09; poj3273,poj3258,poj1905,poj3122 组合数学 poj 3252 题意&#xff1a;如果一个数是round number&#xff0c;则它的二进制表示中&#xff…

推荐2022前端必看的新书 《Vue.js设计与实现》

大家好&#xff0c;我是若川。持续组织了6个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列这本新…

汉堡菜单_汉堡菜单-可访问性和用户体验设计原则的挑战?

汉堡菜单重点 (Top highlight)I was recently designing a hamburger menu for a client and before I knew it, I had embarked on this journey where I was reading article after article about the accessibility issues which accompany a hamburger icon. Turns out, th…

Server2012R2 ADFS3.0 The same client browser session has made '6' requests in the last '13'seconds

本问题是在windows server2012R2系统ADFS3.0环境下遇到的&#xff0c;CRM2013部署ADFS后运行一段时间(大概有一两个月)后在IE浏览器中访问登陆界面点击登陆后就报以下错误 “Microsoft.IdentityServer.Web.InvalidRequestException: MSIS7042: The same client browser session…

又一个基于 Esbuild 的神器!esno

大家好&#xff0c;我是若川。持续组织了6个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan02 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列esno我…

c# ui 滚动 分页_UI备忘单:分页,无限滚动和“加载更多”按钮

c# ui 滚动 分页重点 (Top highlight)When you have a lot of content, you have to rely on one of these three patterns to load it. So, which is best? What will your users like? What do most platforms use? These are the questions we will explore today.当内容…

少年,看你异于常人,有空花2小时来参加有3000人的源码共读嘛~

大家好&#xff0c;我是若川。按照从易到难的顺序&#xff0c;前面几期&#xff08;比如&#xff1a;validate-npm-package-name、axios工具函数&#xff09;很多都只需要花2-3小时就能看完&#xff0c;并写好笔记。但收获确实很大。开阔视野、查漏补缺、升职加薪。已经有400笔…

16位调色板和32位调色板_使调色板可访问

16位调色板和32位调色板Accessibility has always been a tough sell. Admittedly, less so than in the ‘nineties, when no prospective client was interested. But even today — more enlightened times — the majority of companies I encounter still prefer to make …

从零开始发布自己的NPM包

大家好&#xff0c;我是若川。持续组织了6个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan02 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列在Ver…

Jest + React Testing Library 单测总结

大家好&#xff0c;我是若川。持续组织了6个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan02 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列1、背…

着迷英语900句_字体令人着迷

着迷英语900句I’m crazy about fonts. My favorite part of any text editing software is the drop down menu for picking fonts. When I look at any text, I try to identify the font. Roboto is my favorite font.我为字体疯狂。 在任何文本编辑软件中&#xff0c;我最喜…

推荐一个大佬,文章适合偷偷读!

大家好&#xff0c;我是若川。周末愉快。也许你看到这篇文章是周一的上午~我不得不推荐一位大佬给你&#xff01;这位大佬的文章很硬&#xff0c;却一直在「抱怨没有粉丝&#xff0c;没人愿意分享」我去读了读&#xff0c;尼玛这个「谁TM敢分享啊」&#xff0c;文章太「违规」了…

PERFORMANCE-MONITORING(转)

Performance-Monitoring 是Intel提供的可以监测统计CPU内部所产生事件的一组方法。在Intel的手册上介绍了两类CPU事件监测方法&#xff1a;architectural performance monitoring 和 non-architectural performance monitoring。Architectural performance monitoring与平台&am…

ux设计_为企业UX设计更好的数据表

ux设计重点 (Top highlight)If you have worked on enterprise products, you must have noticed the use of lots of data tables. Therefore, I am writing this article to collect the most common use cases and discuss how elegantly we can handle them.如果您使用过企…

狼叔直播 Reaction《学习指北:Node.js 2022 全解析》

大家好&#xff0c;我是若川。持续组织了6个月源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan02 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列本文是…

figma下载_Figma中的高级图像处理

figma下载Figma is not exactly suited for image manipulation, and that’s completely fine. While it does provide an ample amount of tools that let you apply some basic changes to your raster images, for anything more complex you need to look someplace else.…