在 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" />
会一次性全部渲染,而不会进行懒加载。