导图社区 vue3文档导图
这是一篇关于vue3文档导图的思维导图,包含基础、组件、生命周期等。干货满满,感兴趣的小伙伴可以参考使用!
编辑于2023-12-22 09:04:24vue
基础
创建应用
createAPP
步骤
应用配置
响应式
ref
.value
getter追踪
setter触发
深层响应性
作为响应式对象的属性时,自动解包成普通属性
只有当ref对象是响应式对象的顶层属性或被嵌套在响应式对象中时,它才会自动解包。在其他情况下,需要使用ref.value来访问其值
reactive
返回原始对象的Proxy,与原始对象并不相等
只能是引用类型
不能替换整个对象,以便保留响应性
解构不友好
响应式丢失
toRefs 保持响应性
理论
响应式对象——js代理
访问和修改
依赖追踪、触发更新
工具
isRef
判断是否为 ref , 返回 boolean
unref
语法糖: val = isRef(val) ? val.value : val
toRef
基于响应式对象上的某个属性,创建一个对应的ref,新ref跟源属性保持同步
应用场景
props值不能修改,基于props创建的 ref 可以做出变更(酌情添加watch监听)
toRefs
将一个响应式对象转为普通对象,但为每个属性用 toRef 创建对应的ref
只针对可枚举的属性创建ref
注意
toRefs 解构不丢失响应性
shallowRef
ref的浅层处理
只处理基本数据类型的响应式, 不进行对象的响应式处理
triggerRef
将ref 生成的数据强制更新ui
customRef
显式声明对某个ref 进行依赖追踪和更新触发的控制方式
使用场景
防抖
shallowReactive
reactive() 的浅层作用形式
只对第一次数据做响应式处理,深层数据只是普通对象
toRaw
返回创建的代理的原始对象,即把响应式对象转为普通对象
作用
临时读取,不引起代理访问、追踪开销
写入时不触发更改方法
不建议持久引用,仅临时用
markRaw
标记为普通对象,无法被转成响应式对象
computed
不要做异步请求或更改DOM
不要直接修改计算属性值
默认只读
强制修改:get(), set(newValue)
类与样式绑定
:class
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
可配合computed
数组: <div :class="[activeClass, errorClass]"></div> const activeClass = ref('active') const errorClass = ref('text-danger')
结果:<div class="active text-danger"></div>
三元表达式: <div :class="[isActive ? activeClass : '', errorClass]"></div>
嵌套: <div :class="[{ active: isActive }, errorClass]"></div>
给子组件设置class,会追加
:style
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
支持驼峰和'font-size' 2种写法
自动添加前缀
样式多值: <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
v-for
自动更新
push
pop
shift
unshift
splice
sort
reverse
事件
@click
修饰符
.stop
停止传递事件
.prevent
阻止事件默认行为
.self
只对事件目标本身进行监听
.captrue
补货模式:先被外部事件处理
.once
只触发一次
.passive
该事件监听器不会阻止事件的默认行为
避免浏览器在执行事件处理函数之前进行不必要的布局计算或绘制
按键修饰符
<!-- 仅在 `key` 为 `Enter` 时调用 `submit` --> <input @keyup.enter="submit" />
<input @keyup.page-down="onPageDown" />
<!-- Alt + Enter --> <input @keyup.alt.enter="clear" /> <!-- Ctrl + 点击 --> <div @click.ctrl="doSomething">Do something</div>
案例
v-model
修饰符
.lazy
change后同步更新
.number
自动转为数字
无法被 parseFloat 处理,将返回原始值
type="number"时自动启用
.trim
自动去除俩端空格
使用对象
文本
input/ textarea
radio / checkbox
select
组件
侦听器
watch
单个 ref
watch(x, (newX) => {})
深层监听
监听对象的某个属性
watch(() => x.value + y.value,(sum) => {})
监听多个值
watch([x, () => y.value], ([newX, newY]) => {})
附加
强制监听:{deep:true}
立即执行回调: {immediate: true}
特点
适合追踪明确数据源
仅当依赖项发生变化时执行
递归跟踪所有的
watchEffect
组件每次更新都会执行
自动收集依赖项
自动重新编译和运行
特点
仅在副作用发生期间追踪使用到的依赖,不递归追踪所有
维护多个依赖项,消除手动维护依赖列表的负担
访问更新后的DOM:{flush: 'post'}
停止
同步创建(默认)
自动绑定到组件实例,组件卸载自动停止
异步创建
不会绑定到当前组件,需手动停止,以防内存泄漏
const unwatch = watchEffect(() => {}) unwatch() // watch同样
模板引用
ref="xx"
ref数组与源数组顺序不一定
模板
子组件
子组件添加以下才可被父组件访问: const a = 1 const b = ref(2) defineExpose({a,b})
父组件自动对a,b解包
组件
单文件组件SFC
props
setup方式
defineProps(['xx'])
编译宏命令,不需导入
返回对象
vue2方式
props: ['xx']
单向数据流,避免影响父组件
验证规则
默认可选,除非 required: true
Boolean 默认为false, 其他default:xxx或undefined
动态组件
<component :is="xx"></component>
可配合<KeepAlive>缓存
注册
全局
app.component('组件名', 导入的组件或者组件的实现)
链式调用,使用多个
缺点
无法自动移除(tree-shaking)
关系不明朗、不易维护
局部
components:{}
组件名需横杠写法,因为浏览器忽略标签大小写
事件
自定义事件
$emit
父组件通过@监听事件,即 v-on
支持.once修饰符
声明触发的事件
defineEmits()
只能在 setup()下
若是显式 setup(),需要通过 emits选项定义数组
可解构
参数
字符串数组
每个字符串都代表一个事件,使用: emit('xx')
对象(对参数验证)
const emit = defineEmits({ submit(payload: { email: string, password: string }) { // 通过返回值为 `true` 还是为 `false` 来判断 // 验证是否通过 } })
v-model
update:value
属性更新事件
value + 修饰符
修饰符的值为:props.vale+'Modifiers'
透传 Attributes
继承
class
style
v-on
深层组件
{{ $attrs }} 访问
除去props和emits 都可访问
大小写保持一致
例如: $attrs['foo-bar']
v-on事件监听器暴露为函数 $attrs.onClick
v-bind="$attrs" 会把所有属性都绑定
禁用继承
defineOptions({ inheritAttrs: false })
多个根节点的组件没有自动 attribute 透传行为
抛出警告
$attrs 被显式绑定,则不会有警告
js 中访问所有透传
组合式
import { useAttrs } from 'vue' const attrs = useAttrs()
选项式
setup(props, ctx) {console.log(ctx.attrs)}
非响应式(影响性能)
不能通过侦听器监听
解决
使用prop或onUpdated
slot 插槽
渲染作用域
父组件
具名插槽
添加name属性,name唯一性
使用
父:<template v-slot:header> <!-- header 插槽的内容放这里 --> </template>
简写:<template #header>
子:<slot name="footer"></slot>
默认为default
动态插槽名
<template v-slot:[dynamicSlotName]>
简写:<template #[dynamicSlotName]>
插槽传值(子传父)
默认插槽使用
子:<slot :text="greetingMessage" :count="1"></slot>
父:<MyComponent v-slot="slotProps"> {{ slotProps.text }} {{ slotProps.count }} </MyComponent>
解构简写: <MyComponent v-slot="{ text, count }"> {{ text }} {{ count }} </MyComponent>
具名插槽使用
子:<slot name="header" message="hello"></slot>
父:<template #header="headerProps"> {{ headerProps }} </template>
输出: { message: 'hello' }
同时使用
需显式使用默认插槽
无渲染组件
只做逻辑处理,没有视图渲染
依赖注入
provide:提供
provide(注入名:string,值:any)
支持响应式
支持传递事件
支持readonly(值):inject无法更改
inject: 注入
const value = inject ( 注入名:string,默认值(可选):any)
工厂模式: const value = inject('key', () => new ExpensiveClass(), true)
支持解构
异步组件 defineAsyncComponent
注册方式
服务器获取
const AsyncComp = defineAsyncComponent(() => { return new Promise((resolve, reject) => { resolve(/* 从服务器获取组件 */) })})
ES模块动态导入(父组件注册)
const AsyncComp = defineAsyncComponent(() => import('./components/MyComponent.vue'))
全局注册
app.component('MyComponent', defineAsyncComponent(() =>import('./components/MyComponent.vue')))
加载与错误状态
const AsyncComp = defineAsyncComponent({ loader: ()=> import(''), // 加载组件的回调 loadingComponent: LoadingComponent, // loading组件 delay: 300, // 默认200ms延迟 errorComponent: ErrorComponent, // 加载失败后展示 timeout: 3000 })
动态组件 <component :is=""></component>
切换时自动卸载
配合<KeepAlive>
js 中属性为驼峰式写法,html中适合横杠写法
生命周期(都是回调函数)
setup
挂载
onBeforeMount
响应式状态设置完成,DOM还没创建
onMounted
组件完成初始渲染并创建 DOM 节点
同步子组件,不包括异步组件或<Suspence>内的组件
<KeepAlive>专有钩子
onActivated
组件插入到DOM时
onDeactivated
组件从 DOM 中被移除时
更新
onBeforeUpdate
变更前
onUpdated
子组件先与父组件
销毁
onBeforeUnmount
组件实例被卸载之前
onUnmounted
组件实例卸载后
子组件全被卸载
所有响应式作用都已经停止
错误
onErrorCaptured
捕获了后代组件传递的错误时
错误来源
组件渲染
事件处理器
生命周期狗子
setup()
侦听器
自定义指令钩子
过渡钩子
参数
错误对象
触发该错误的组件实例
错误来源的信息字符串
返回值 boolean | void
false: 阻止错误继续向上传递
注意
建议更改组件状态,显示错误状态。渲染错误内容会导致组件无限循环
传递规则
默认错误发送到 app.config.errorHandler()。前提是这个函数已经定义。
继承链或组件链存在多个errorCaptured,对于同个错误会从底至上按序调用,即“向上传递”,类似冒泡机制
errorCaptured错误也会发送给 app.config.errorHandler
dev专用
onRenderTracked
当组件渲染过程中追踪到响应式依赖时
onRenderTriggered
当响应式依赖的变更触发了组件渲染时
SSR专用
onServerPrefetch(异步回调函数)
在组件实例在服务器上被渲染之前调用
内置组件
Transition
所有子组件都共享组件状态的过渡和变化
触发条件
v-if
v-show
动态组件<component :is="xxx">
改变特殊的 key 属性
组件中元素插入或移除时
自动检测元素是否应用css过渡或动画
检测是否有钩子函数,并执行
onBeforeEnter
元素插入前执行
onEnter
元素插入后的下一帧调用
有完成回调 done()
onAfterEnter
过渡完成时调用
onEnterCancelled
过渡完成前被取消
onBeforeLeave
离开状态前
onLeave
元素移除时
有完成回调 done()
onAfterLeave
元素移除完成
onLeaveCancelled
仅在 v-show 过渡中可用
如果以上都无,则在下一帧后执行
浏览器以每秒60帧的速度更新,即动画帧,每一帧都是一个渲染周期
KeepAlive
<!-- 非活跃的组件将会被缓存! --> <KeepAlive> <component :is="activeComponent" /> </KeepAlive>
include / exclude
3种定义规则
<KeepAlive include="a,b">
<KeepAlive :include="/a|b/">
<KeepAlive :include="['a', 'b']">
需要配合 v-bind
最大缓存实例数
<KeepAlive :max="xx">
生命周期
onActivated
首次挂载
每次从缓存中被重新插入
onDeactivated
从dom移除、进入缓存
组件卸载
触发条件
Suspense
作用
在组件树中对异步依赖处理,等待所有子级异步解析完成,并可渲染一个加载状态
异步依赖
async setup() (组合式API默认自带)
异步组件
默认加载、报错、延时、超时等都由<Suspense>代理
取消<Suspense>代理控制
异步组件设置: suspensible: false
加载中状态(2个插槽)
#default
#fallback
只会渲染其中一个节点
初期渲染#default
异步则挂起,渲染#fallback
完成再次渲染为#default
除非根节点被替换,否则无论怎么变都不会再被挂起
发生回退时,不会立即#fallback,根据timeout属性延迟,默认为0,则立即#fallback
此处slot都只允许一个直接子节点
事件
pending
resolve
fallback
类似promise3个状态事件
错误处理
errorCaptured选项
onErrorCaptured钩子
router
vuex
pinia
cli