组合式API
针对数据定义
ref:可以定义任意类型的响应式数据,在js中取值、赋值,需要用数据.value,在模板中,直接使用就行;如果修饰引用类型数据,value值是一个Proxy对象。
reactive:只能修饰引用类型数据,是一个Proxy对象。
shallowRef:ref对数据的监听是深层次监听,shallowRef是浅层次的监听;ref监听数据是将原数据进行拷贝,监听的是拷贝的数据,shallowRef只监听原数据。
toRaw:将响应式数据转成原数据。
toRef:将一个非响应式数据修饰成响应式的数据。
toRefs:将一个reactive对象中的每个属性都转成ref响应式数据,此时模板中使用这个属性值的时候,需要.value。
shallowReactive:是一个浅层次监听的Proxy对象。
readOnly:让一个数据变成只读数据。
shallowReadOnly:让浅层次的数据变成只读的,深层次还可以修改。
检测对象的方法
isRef:判断一个数据是否是一个ref对象
isReactive:判断一个对象是否有reactive创建的响应式对象
isReadonly:判断一个对象是否有readonly创建的只读数据
isProxy:检查一个对象是否是由reactive或readonly方法创建的响应式数据
比较常用的API
watch:监听器,监听某个数据发生变化,就执行一段逻辑
watchEffect:立即执行的监听器,第一次就会执行;这个函数中用到的数据变化就会执行,不用指定监听某个数据。
computed:计算属性,得到一个依赖其他数据变化重新计算得到新数据的方法。
nextTick:数据更新后,vue内容会更新视图,更新视图的操作是异步的。如果要获取到更新后的视图或dom节点,就使用nextTick。(nextTick的回调函数在调用的时候,是在一个异步的回调函数中执行的,这个异步任务是宏任务还是微任务?首先为了性能先用了微任务,如果微任务出错了会调用宏任务)
跟数据传递相关的
defineProps:用于接收父通过属性给子传递的数据
defineEmits:用于接收父给子绑定的事件
defineExpose:用于将自己的数据或方法暴露出去
getCurrentInstance:用于获取当前组件实例对象
生命周期钩子函数
在vue3的setup语法糖中,直接就是创建后的阶段,所以在组合式API中是没有创建前后的钩子函数。
onBeforeMount:挂载前
onMounted:挂载后
onBeforeUpdate:更新前
onUpdated:更新后
onBeforeUnmount:销毁前
onUnmounted:销毁后
事件循环
js是一门单线程语言,也就意味着js同一时间只能做一件事,无法同时进行多个任务,也就造成了运行的性能比较低。
为了提高性能,js内置了异步的任务,希望同一时间,能进行多个任务。
异步任务跟单线程是有冲突、矛盾,js利用好基友浏览器去处理了异步任务。
js执行js代码的时候,首先会直接在自己的线程中执行同步代码,碰到异步代码的时候,会交给浏览器的webapi去处理,浏览器的处理只是在等待这段代码要执行的时机,当等到这段代码执行的时机后,会将需要执行的代码放在一个队列中。js线程将所有同步任务执行结束后,会从队列中依次将代码放在js线程中去执行。
异步任务分两种,所以队列分两种:
宏任务会放在宏队列中,微任务会放在微队列中。
宏任务:每隔一段时间执行的定时器 + 延迟执行的定时器 + 原生ajax
微任务:Promise的then和catch + await
js线程将所有同步代码执行结束后,会先清空微队列,然后再去清空宏队列,然后再清空微队列,然后再清空宏队列。。。。
将整个script代码当做是一个宏任务,先清空宏队列,再清空微队列,。。。
组件通信
- 父传子
父组件中在子组件标签上添加属性,就是给子组件传递数据
子组件中通过defineProps接收数据
- 子传父
父组件中在子组件标签上绑定事件(自定义事件名称),事件函数在父组件中定义的
子组件中通过defineEmits接收事件
子触发事件,并传递实参
父组件的事件函数中可以通过形参接收数据
- ref
直接获取子组件实例就能获取到子组件的数据和方法了
父组件中定义ref数据,值为空
在父组件中给子组件标签添加ref属性,值是定义好的ref数据
子组件中将父组件需要的方法和数据通过defineExpose暴露出去
父组件通过ref数据.value获取到子组件实例对象,其中就有数据和方法
父给子传递数据:
在父组件中给子组件标签添加ref属性,值是定义好的ref数据
子组件中将父组件需要的函数通过defineExpose暴露出去
父组件通过ref数据.value获取到子组件实例对象,其中就有暴露出来的函数
函数调用,传递实参
在子组件中定义函数的地方可以使用形参接收
- 祖孙组件数据传递
provide传递和inject接收。
provide在祖组件中提供数据 ==> 传递
inject在孙组件中接收数据 ==> 接收
祖向孙传递数据:
祖用provide(键, 值)传递
孙用inject(键)可以返回一个值
孙向祖传递数据:
祖用provide传递一个函数
孙用inject接收函数,调用函数传递实参
祖定义的函数中,使用形参进行接收
- 插槽
插槽通常传递的不是数据,是页面结构。
默认插槽:
具名插槽:
作用域插槽:
- vuex和pinia
- 透传(给子组件标签添加属性,如果子组件没有使用props接收,就会将这个属性放在子组件最大的标签上,例如给子组件标签添加style、class)
- 全局数据
在main.ts中,给app.config.globalProperties.属性名赋值,这个属性名就是全局的数据名称,我们可以在任意组件中使用。
- 利用第三方插件 mitt
下载安装:
npm i mitt
单独封装一个文件:
import mitt from 'mitt'
const bus = mitt()
export default bus
在组件中可以绑定事件,可以触发事件:
bus.on(事件名称, 函数) // 绑定事件
bus.emit(事件名称, 参数) // 触发事件并传递数据
总结:
看完了吗?不知道你看完后是否有所收获,本文是从使用层面及一些日常应用示例上去分析的,并没有深层次剖析。建议还是去看官方的源码哦。