>首页> IT >

环球观热点:聊聊Vue2开发者如何快速上手Vue3

时间:2022-07-26 20:01:47       来源:转载
如何快速上手Vue3?下面本篇文章给大家对比一下Vue2和Vue3,并介绍一下Vue2开发者如何快速上手Vue3,希望对大家有所帮助!

笔者之前是Vue2+React开发者,因项目需要直接上手Vue3,所以快速学习一下,中间会对比一些和React相关的区别。阅读前提:已经上手了Vue2的开发,本文主要聊的问题:

Vue3的全新特性


(资料图)

Vue2和Vue3的一些区别

Vue2开发者如何快速上手Vue3

Vue3和React的简单比对

使用Vue3编写组件库

(学习视频分享:vue视频教程)

Vue2 vs Vue3


1、简单点说

Vue2只支持单节点,Vue3 template支持多节点,类似react fragments变化基本都在script中(Option api -> Composition api)不会再看见满屏的this了!!!style支持v-bindProxy代替definePropertydefineProperty无法实现对数组对象的深层监听,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-repovue2.x的源码托管在src目录中,然后依据功能拆分出了complier(模板编译的相关代码),core(与平台无关的通用运行时代码),platforms(平台专有代码),server(服务端渲染的相关代码)、sfc(.vue 单文件解析相关代码)、shared(共享工具代码) 等目录vue3 mono-repopackage可以独立于vue.js去使用,这样例如用户想要使用vue3.0的响应式,可以单独依赖reactive,而不必依赖整个vue.js,减少引用包的体积,而vue2.x却做不到这一点。

源码结构对比

全新的API


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

解决了过去组件过长时,optionsApi带来的难以维护的问题逻辑可以整块复用所有API都是import引入的,对Tree- shaking很友好,没用到功能,打包的时候会被清理掉,减小包的大小

1、setup

新的 setup选项在组件被创建之前执行,一旦 props被解析完成,它就将被作为组合式 API 的入口。可以当做Vue2的beforeCreate和create生命周期用可直接写await语法SFC单文件组件中直接使用<script lang="ts" setup>即可,或者也可以结合export default使用
<script setup>const result = await Http.get("/getUserInfo")</script>// 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})

相关api

Refts定义 import { type Ref } from "vue";isRef判断是否为ref对象。一般是ref,toRef,toRefs创建的变量toRefsreactive对象解构为单个响应式对象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 作为标题,现在是 refconsole.log(book.title) // "Vue 3 Detailed Guide"

4、生命周期

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

<script setup>import { onMounted } from "vue";const getUserInfo = () => {  console.log("获取用户信息");};onMounted(getUserInfo);</script>

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 = 1console.log(counter.value) // 0counter.value++console.log(counter.value) // 1console.log(twiceTheCounter.value) // 2

组件


1、异步组件

通过进行引入defineAsyncComponent可配合Suspense 进行更多操作,可用于loading和骨架屏相关,和react Suspense基本一致。不过react Suspense基本一致这个属性都不太好用,vue的不清楚实际场景咋样
// template    // scriptconst 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

defineProps 代替过去的propsdefineEmits 代替过去的$emitdefineOptions 自定义一些组件属性,比如组件名称(需要插件支持)defineComponent 用于render函数、TSX、IDE提醒等defineExpose 子组件声明的数据,暴露给父组件直接用

provide/inject

和vue2一致

vuex & pina

Vuex: State、Gettes、Mutations(同步)、Actions(异步)Pinia: State、Gettes、Actions(同步异步都支持)Vuex4 用于 Vue3 ,Vuex3 用于 Vue2Pinia2.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

<script>    export default {        name: "TButton",    };</script><script setup>  defineOptions({    name: "TButton",  });</script>

2、vscode插件

volar vscode

vetur只支持vue2,volar只支持vue3,两者冲突。建议禁用vetur,格式化代码使用prettier,本地使用volar做代码高亮。

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

指令


1、v-model

底层语法糖时间改变,之前vue2是update:input,vue3 是update:modelValue支持多个v-model支持自定义修饰符弃用.sync等

2、自定义指令

生命周期(和vue3一致)

created 元素初始化的时候beforeMount 指令绑定到元素后调用 只调用一次mounted 元素插入父级dom调用beforeUpdate 元素被更新之前调用update 这个周期方法被移除 改用updatedbeforeUnmount 在元素被移除前调用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写

// useWindowResizeimport { 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-vuev3hooks

3、react vs vue3

Vue3 究竟好在哪里?(和 React Hook 的详细对比)ssh-晨曦时梦见

结语


Vue3 的依赖追踪是全自动的,不需要担心传了错误的依赖数组给 useEffect/useMemo/useCallback 从而导致回调中- 使用了过期的值

Vue3 Hook也没React Hook那么多限制,后续用用看怎么样

个人比较喜欢SFC语法,html、js、css分离开

本文所有demo都在该仓库中JJ-UI 一款Vue3组件库,参考大佬文章刚刚搭建好,后续会基于这个架子开发自己的vue3组件库

【相关视频教程推荐:vuejs入门教程、web前端入门】

以上就是聊聊Vue2开发者如何快速上手Vue3的详细内容,更多请关注php中文网其它相关文章!

关键词: 生命周期 视频教程 引用类型