在 Vue3 学习中,之前有些知识理解不是很到位,专门抽时间查缺补漏,备忘如下。

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