在 Vue3 学习中,之前有些知识理解不是很到位,专门抽时间查缺补漏,备忘如下。
v-bind:attribute="value"
会将attribute
值绑定为value
。如果绑定的值是null
或undefined
,那么该attribute
将(显式)从元素上移除。v-bind="object"
会绑定object
对象的所有键值对。v-bind
用于将一个包含多个attribute
的对象绑定到单个元素上。实际调用的是mergeProps(...args)
方法,参数分为三部分:v-bind
之前的属性对象(attribute: value
),v-bind
绑定的对象,v-bind
之后的属性对象(attribute: value
),三部分依次作为参数传入。mergeProps
支持将class
,style
,onXxx
事件监听器(多个同名事件监听器将被合并成一个数组)合并成一个对象。如果不需要合并行为而是简单的覆盖,可以使用Object.assign({}, object)
或者{ ...object }
。v-xx[dynamic]
动态参数dynamic
期望值为字符串或null
。null
表示移除该绑定。- 响应式状态需要使用响应式 API 创建,即
ref()
和reactive()
。ref()
接收一个值,返回一个响应式的可更改的ref
对象。如果将对象赋值给ref
,这个对象将通过reactive()
转为深层响应性的对象。这也意味着,如果对象包含嵌套的ref
,它们也会被深层解包。reactive()
返回一个对象的响应式代理。响应式转换是深层的:它会影响所有嵌套属性。响应式对象也会深层解包ref
属性同时维持响应性。同时要注意的是,当访问响应式数组或者原生集合(如Map
)的ref
元素时,它不会被解包。将一个ref
赋值给reactive()
属性时,ref
会自动解包。
- 通过
setup()
返回的ref
在模板中作为顶层变量使用时自动解包;父组件通过模板ref
获取组件实例时,实例上的ref
也一样自动解包。 setup(props)
中props
是响应式的reactive()
,解构会丢失响应性,因此推荐始终以props.xxx
形式访问。如果要解构props
,可以使用toRefs()
和toRef()
维持响应性。为props
中对象或数组指定的默认值必须从工厂函数返回。setup(props, context)
中context
有四个属性:非响应式对象attrs
(等同$attrs
),非响应式对象slots
(等同$slots
),函数emit
(等同$emits
),函数expose
。context
对象是非响应式的,可以安全解构。attrs
和slots
都是有状态的对象,它们总会在组件更新时更新。这意味着应该避免解构它们,而总是以attrs.x
或slots.x
的形式引用。如果要基于attrs
或slots
改变来应用 side effect,则应放在onBeforeUpdate
生命周期钩子中。- 透传
attribute
:attribute
或者v-on
事件监听器传递给组件,但在接收的组件props
或emits
中未显式定义。最常见的例子包括class
,style
,id
属性。如果组件定义了props
或者v-on
,就会被消费而不继续往下继承。- 当组件渲染单节点元素,透传
attribute
会自动添加到根节点attribute
。 $attrs
包含除了props
或emits
选项外的所有属性。(如class
,style
,v-on
等)- 注意:不像
props
,在 JavaScript 中透传属性保留了它们原来的大小写,所以像一个属性foo-bar
需要通过$attrs['oo-bar']
访问。 v-on
如@click
会被暴露为$attrs.onClick
。
- 当组件渲染单节点元素,透传
- 虽然
attrs
总是反应为最新的透传属性,但它并不是响应式的(考虑到性能因素)。不能通过侦听器watch
去监听它的变化。如果你需要响应性,使用props
。或者,使用onUpdated()
在每次更新时使用最新的attrs
来执行副作用。 props
和v-on
会按组件上attribute
出现的顺序进行合并:<Component :onClick=“func1” @click=“func2” /> props.onClick = [func1, func2]; <Component @click=“func2” :onClick=“func1” /> props.onClick = [func2, func1];
reactive()
的局限性:- 仅对对象类型有效(对象、数组和
Map
、Set
这样的集合类型),而对string
、number
和boolean
这样的原始类型无效; - 因为 Vue 的响应式系统是通过属性访问进行追踪的,因此必须保持对该响应式对象的相同引用。不可以随意「替换」响应式对象,这将导致对初始引用的响应性连接丢失。同时也意味着将响应式对象的属性赋值或解构至本地变量时,或将该属性传入函数时,将丢失响应性。
- 仅对对象类型有效(对象、数组和
ref()
值为对象时,可以响应式的替换整个对象。被传递给函数或从普通对象上解构时,不会丢失响应性。- Vue 生命周期钩子调用不一定非要放在
setup()
或<script setup>
代码块中,只要调用栈是同步的并且源自setup()
,也可以放在外部函数中。 - 使用服务端渲染(SSR)时,服务端和客户端创建应用都要使用
createSSRApp()
,客户端不要使用createApp()
,不然会出现一些问题,例如<img loading="lazy" />
会一次性全部渲染,而不会进行懒加载。