基于vue2,现公司要求要用vue3框架来开发,于是利用此机会来记录vue3的学习内容。以便后续开发使用。
- 打包大小减少41%
- 初次渲染快55%, 更新渲染快133%
- 内存减少54%
- 重写虚拟DOM的实现和Tree-Shaking
- 使用Proxy代替defineProperty实现响应式
- Vue3可以更好的支持Typescript
- 生命周期改变
- 新增了组合式API(setup、ref,reactive…)
- 推荐使用vite创建vue3项目(构建工具)
- 根标签可使用多个,vue2中只能使用一个
- 新的内置组件(Teleport、Suspense…)
- vue3向下兼容vue2
使用npm create vue@latest 创建 (基于 Vite 创建项目)
- 默认为一个函数return {}可供html中自行使用。
- setup函数,可以和vue2中写法data和methods同时使用,但是不建议使用。
- data中能读取setup中数据,setup中不能读取data中数据。
- 执行时机,比beforeCreate早。
setup语法糖: 直接在标签中写上setup,即直接把函数和单一的参数直接写即可,在模板中即可直接使用,不需要return。
给组件添加name: 方法一、 再写一个script,一个vue文件中包含两个script
方法二、 使用插件: npm install vite-plugin-vue-setup-extend -D 再在vite.config.ts中进行配置
- 引入ref
- ref()函数包裹即是响应式数据,可以使用基本类型的,也可以定义对象(底层使用reactive)
- 修改时需要使用xx.value进行修改
- 再模板中直接使用xx即可
1、基本类型
2、对象类型 底层还是使用reactive来处理响应
- 引入reactive
- 使用该函数包裹对象
- 使用时直接xx.xx
- 可深层次响应
1、ref创建的变量必须使用.value(可以使用volar插件自动添加.value)。 自动补充value 2、reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)。 reactive:
ref:
使用原则:
- 若需要一个基本类型的响应式数据,必须使用ref。
- 若需要一个响应式对象,层级不深,ref、reactive都可以。
- 若需要一个响应式对象,且层级较深,推荐使用reactive(表单表格这种)。
解构出来的数据不是响应式,通过toRefs(多个)toRef(单个)方式变成响应式。
let {name,name1,。。。} = (obj) let name = (obj,“name”)
== 注意:使用ref()包含的对象,解构时,也一样不是响应式数据,也需要使用toRefs与toRef才行。==
- 引入computed,是一个函数
- let item = computed(()=>{}) 只读
- let item = computed({set(){},get(){}}) 可修改
:监视数据的变化(和Vue2中的watch作用一致) :Vue3中的watch只能监视以下四种数据:
- ref定义的数据。
- reactive定义的数据
- 函数返回一个值(getter函数)
- 一个包含上述内容的数组
情况一:
监视ref定义的【基本类型】数据:直接写数据名即可,监视的是其value值的改变。
情况二、
监视ref定义的【对象类型】数据:直接写数据名,监视的是对象的【地址值】,若想监视对象内部的数据,要手动开启深度监视。 注意: 1、若修改的是ref定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。(开启深度监视) 2、若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。 一、修改整个对象,监听写法:
一、修改对象属性,监听写法:
情况三、
监视reactive定义的【对象类型】数据,且默认开启了深度监视。并且深度监听关不掉。改变数据时,应用地址不会发生改变,则newVal,oldValue会保持一致。
情况四、
监视ref或reactive定义的【对象类型】数据中的某个属性,注意点如下:
若该属性值不是【对象类型】,需要写成函数形式。 若该属性值是依然是【对象类型】,可直接编,也可写成函数,建议写成函数。(直接编写会出现问题) 结论:只要想监视对象里的属性,就写函数式,注意点:若是监视的是地址值(对象),想要关注对象内部变化,需要手动开启深度监视。
情况五、
监视上述的多个数据,使用数组的方式组合在一起。
官网:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。
watch对比watchEffect:
- 都能监听响应式数据的变化,不同的是监听数据变化的方式不同
- watch:要明确指出监视的数据。watchEffect:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)。 3.watchEffect监听多个数据时可以使用此
作用:用于注册模板引用,和vue2作用一致,写法略有区别。
- 用在普通DOM标签上,获取的是DOM节点。
- 用在组件标签上,获取的是组件实例对象。
一、用在普通DOM标签上:
二、用在组件标签上: 使用ref对数据有保护作用,即在子组件中要通过defineExpose来导出数据供父组件拉使用。 父组件:
子组件:
…后续补充
:泛型,限定类型 :接收传入的值,可限定类型 :设置默认值
生命周期整体分为四个阶段,分别是:创建、挂载、更新、销毁,每个阶段都有两个钩子,一前一后。
- Vue2的生命周期
创建阶段:beforeCreate、created 挂载阶段:beforeMount、mounted 更新阶段:beforeUpdate、updated 销毁阶段:beforeDestroy、destroyed
- Vue3的生命周期
创建阶段:setup 挂载阶段:onBeforeMount、onMounted 更新阶段:onBeforeUpdate、onUpdated 卸载阶段:onBeforeUnmount、onUnmounted
注意:子组件mounted生命周期快于父组件mounted
什么是hook?—— 本质是一个函数,把setup函数中使用的Composition API进行了封装,类似于vue2.x中的mixin。
自定义hook的优势:复用代码, 让setup中的逻辑更清楚易懂。每个hooks可以写生命周期函数以及计算属性等…
实例代码: useSum.ts中内容如下:
组件中具体使用:
一、基本切换效果 Vue3中要使用vue-router的最新版本,目前是4版本。 路由配置文件代码如下:
main.ts代码如下:
App.vue代码如下:
- Routerlink :切换路由,原理就是a标签。
- RouterView:切换路由时,展示区域。
注意点:
1.路由组件通常存放在pages 或 views文件夹,一般组件通常存放在components文件夹。 2.通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。 二、路由模式 1、history模式:
2、hash模式:
** 三、to的两种写法**
四、命名路由 给路由规则命名:
跳转路由:
** 五、嵌套路由** 1、编写News的子路由:Detail.vue 2、配置路由规则,使用children配置项:
3、跳转路由(记得要加完整路径):
4、在Home组件中预留一个进行路由内容展示
六、路由传参 1、query参数: 传递参数:
接受参数:
2、params参数 传递参数:
接受参数:
路由配置:
注意: 1:传递params参数时,若使用to的对象写法,必须使用name配置项,不能用path。 2:传递params参数时,需要提前在规则中占位。 七、路由的props配置 作用:让路由组件更方便的收到参数(可以将路由参数作为props传给组件) 作为props直接传递给组件,供内部使用,这样直接具有响应式。若不用此写法,直接在组件中使用,需要结合toRefs来包装成响应式。 路由写法:
组件中写法:
八、replace属性 作用:控制路由跳转时操作浏览器历史记录的模式。 浏览器的历史记录有两种写入方式:分别为push和replace: push是追加历史记录(默认值)。 replace是替换当前记录。 开启replace模式:
九、编程式导航 路由组件的两个重要的属性:router变成了两个hooks 跳转写法同vue2:
十、重定向 1、作用:将特定的路径,重新定向到已有路由。 2、具体编码:路由中写法
搭建 pinia 环境 第一步:npm install pinia 第二步:操作src/main.ts
存储+读取数据 Store是一个保存:状态、业务逻辑 的实体,每个组件都可以读取、写入它。 它有三个概念:state、getter、action,相当于组件中的: data、 computed 和 methods。 具体编码:src/store/count.ts
组件中使用state中的数据
** 修改数据(三种方式)** 1、第一种修改方式,直接修改
2、第二种修改方式:批量修改
3、第三种修改方式:借助action修改(action中可以编写一些业务逻辑)
组件中调用action即可
storeToRefs 借助storeToRefs将store中的数据转为ref对象,方便在模板中使用。 注意:pinia提供的storeToRefs只会将数据做转换,而Vue的toRefs会转换store中所有数据。所以直接使用的是storeToRefs
getters 概念:当state中的数据,需要经过处理后再使用时,可以使用getters配置。(实际上就是计算属性) 追加getters配置。
组件中读取数据:
** 通过 store 的 $subscribe() 方法侦听 state 及其变化,类似watch**
** store组合式写法** store文件中写法如下,组件中使用的方式与之前一致。
Vue3组件通信和Vue2的区别: 一、props 概述:props是使用频率最高的一种通信方式,常用与 :父 ↔ 子。 若 父传子:属性值是非函数。 若 子传父:属性值是函数。 父组件:
子组件
二、自定义事件 概述:自定义事件常用于:子 => 父。 注意区分好:原生事件、自定义事件。 原生事件: 事件名是特定的(click、mosueenter等等) 事件对象$event: 是包含事件相关信息的对象(pageX、pageY、target、keyCode) 自定义事件: 事件名是任意名称
事件对象$event: 是调用emit时所提供的数据,可以是任意类型!!! 示例:
三、mitt 概述:与消息订阅与发布(pubsub)功能类似,可以实现任意组件间通信。 安装mitt : npm i mitt 新建文件:srcemitter.ts
接收数据的组件中:绑定事件、同时在销毁前解绑事件:
【第三步】:提供数据的组件,在合适的时候触发事件
注意这个重要的内置关系,总线依赖着这个内置关系 四、v-model 1、概述:实现 父↔子 之间相互通信。 2、前序知识 —— v-model的本质
3、组件标签上的v-model的本质::moldevalue + update:modelValue事件。(vue3)( vue2是:model+@input)
AtguiguInput组件中:
4、也可以更换value,例如改成abc
AtguiguInput组件中:
5、如果value可以更换,那么就可以在组件标签上多次使用v-model
五、$attrs
1、概述:$attrs用于实现当前组件的父组件,向当前组件的子组件通信(祖→孙)。
2、具体说明:$attrs是一个对象,包含所有父组件传入的标签属性。
注意:$attrs会自动排除props中声明的属性(可以认为声明过的 props 被子组件自己“消费”了) 父组件
子组件:
孙组件:
六、refs、parent 概述: $refs用于 :父→子。 $parent用于:子→父。 原理如下: ref:可以获取单个组件实例。 $refs 值为对象,包含所有被ref属性标识的DOM元素或组件实例。 $parent 值为对象,当前组件的父组件实例对象。 注意: ref()若被响应式对象包裹,则不需要使用.value拿到值,否则就需要。 7、provide、inject 1、概述:实现祖孙组件直接通信 2、具体使用: 在祖先组件中通过provide配置向后代组件提供数据 在后代组件中通过inject配置来声明接收数据 3、具体编码: 【第一步】父组件中,使用provide提供数据
注意:子组件中不用编写任何东西,是不受到任何打扰的 【第二步】孙组件中使用inject配置项接受数据。
一、 默认插槽 父组件中:
子组件中:
二、具名插槽 父组件中:
子组件中:
三、作用域插槽 理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(新闻数据在News组件中,但使用数据所遍历出来的结构由App组件决定)
具体编码: 父组件中:
子组件中:
一、shallowRef和shallowReactive
作用:创建一个响应式数据,但只对顶层属性进行响应式处理。也就是说只有对 .value 的访问是响应式的。ref则是能深层次进行响应。因此,常常用于对大型数据结构的性能优化,使用方式直接用另外一个值取代这个值。
用法:
作用:创建一个浅层响应式对象,只会使对象的最顶层属性变成响应式的,对象内部的嵌套属性则不会变成响应式的,reactive则是深层次响应式。因此,常常用于对大型数据结构的性能优化,使用方式直接用另外一个值取代这个值。
用法:
总结: 通过使用 shallowRef() 和 shallowReactive() 来绕开深度响应。浅层式 API 创建的状态只在其顶层是响应式的,对所有深层的对象不会做任何处理,避免了对每一个内部属性做响应式所带来的性能成本,这使得属性的访问变得更快,可提升性能。
二、readonly 和 shallowReadonly
作用:用于创建一个对象的深只读副本。其实就是用于保护数据,不可修改。该对象是响应式数据才行。
用法:
特点: 对象的所有嵌套属性都将变为只读。 任何尝试修改这个对象的操作都会被阻止(在开发模式下,还会在控制台中发出警告)。
应用场景: 创建不可变的状态快照。 保护全局状态或配置不被修改。
作用:与 readonly 类似,但只作用于对象的顶层属性。第一层只读,深层次的可修改。
用法:
特点: 只将对象的顶层属性设置为只读,对象内部的嵌套属性仍然是可变的。 适用于只需保护对象顶层属性的场景。
三、toRaw 与 markRaw
作用:用于获取一个响应式对象的原始对象, toRaw 返回的对象不再是响应式的,不会触发视图更新。 官网描述:这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用,请谨慎使用。 何时使用? —— 在需要将响应式对象传递给非 Vue 的库或外部系统时,使用 toRaw 可以确保它们收到的是普通对象
具体编码:
作用:标记一个对象,使其永远不会变成响应式的。 例如使用mockjs时,为了防止误把mockjs变为响应式对象,可以使用 markRaw 去标记mockjs
编码:
四、customRef 作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行逻辑控制。 实现防抖效果(useSumRef.ts): 一般情况下会封装一个hooks,进行使用:
在组件中使用:
一、Teleport 什么是Teleport?—— Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。
这类场景最常见的例子就是全屏的模态框。 二、Suspense 等待异步组件时渲染一些额外内容,让应用有更好的用户体验 使用步骤: 异步引入组件,使用Suspense包裹组件,并配置好default 与 fallback 父组件:
子组件中,使用异步请求。
1、app.component :注册全局组件 将hello.vue组件,注册到全局上,使得所有地方都可以直接使用这个组件。 2、app.config:全局配置属性 3、app.directive 全局配置自定义指令:
v-beauty:“sum”,sum就是value值。 4、app.mount:挂载app组件 5、app.unmount:卸载app组件 6、app.use:使用…模块