vue3文档易忽略细节

1,086 阅读5分钟

Attribute 绑定(注意值为null/undefined情况)

双大括号不能在 HTML attributes 中使用。想要响应式地绑定一个 attribute,应该使用 v-bind 指令

template

<div v-bind:id="dynamicId"></div>

v-bind 指令指示 Vue 将元素的 id attribute 与组件的 dynamicId 属性保持一致。如果绑定的值是 null 或者 undefined,那么该 attribute 将会从渲染的元素上移除。

  • 把对象上的每个属性都绑定(注意属性值为null/undefined的不会被绑定)
<div v-bind="objectOfAttrs"></div>

受限的全局访问(template里受限)

模板中的表达式将被沙盒化,仅能够访问到有限的全局对象列表。该列表中会暴露常用的内置全局对象,比如 Math 和 Date

没有显式包含在列表中的全局对象将不能在模板内表达式中访问,例如用户附加在 window 上的属性。然而,你也可以自行在 app.config.globalProperties 上显式地添加它们,供所有的 Vue 表达式使用。

动态参数

同样在指令参数上也可以使用一个 JavaScript 表达式,需要包含在一对方括号内:

动态属性

<!--
注意,参数表达式有一些约束,
参见下面“动态参数值的限制”与“动态参数语法的限制”章节的解释
-->
<a v-bind:[attributeName]="url"> ... </a>

<!-- 简写 -->
<a :[attributeName]="url"> ... </a>

如果你的组件实例有一个数据属性 attributeName,其值为 "href",那么这个绑定就等价于 v-bind:href

动态事件

你还可以将一个函数绑定到动态的事件名称上:

<a v-on:[eventName]="doSomething"> ... </a>

<!-- 简写 -->
<a @[eventName]="doSomething">

在此示例中,当 eventName 的值是 "focus" 时,v-on:[eventName] 就等价于 v-on:focus

ref(返回ref对象)

  • ref一个对象,返回对象的value属性值是reactive处理后的(proxy)
    //第一个输出是ref返回值,第二个输出是reactive返回值。可见ref一个对象时,它的value和reactive的返回值相同
    image.png
  • 若ref一个基础类型,返回对象的value属性为该基础类型的值
    image.png

动态参数值的限制

动态参数中表达式的值应当是一个字符串,或者是 null。特殊值 null 意为显式移除该绑定。其他非字符串的值会触发警告。

模板里的值非原始data时的方案对比

  1. {{methodes(data)}},通过调用方法的返回值来展示,绑定在表达式中的方法在组件每次更新时都会被重新调用
  2. computed运算,有缓存,节省性能

通过key的变动触发过渡/组件生命钩子

  • 如果某个prop改变时,想触发子组件生命周期钩子可以加key
<transition>
  <span :key="text">{{ text }}</span>
</transition>

当 text 变化时,<span> 总是会被替换而不是更新,因此 transition 将会被触发。

template配合v-if/v-for

  • 最后渲染的结果并不会包含这个 <template> 元素。
  • template不能配合v-show 因为v-show是修改dom的display属性,但template根本不会渲染成dom
<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

在 <template> 标签上使用 v-for 来渲染一个包含多个元素的块。例如:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-if v-for

  • 在vue2中,v-for的优先级高于v-if;在vue3中,v-if的优先级高于v-for
    当它们同时存在于一个节点上时,v-if 比 v-for 的优先级更高。这意味着 v-if 的条件将无法访问到 v-for 作用域内定义的变量别名
    在外新包装一层 <template> 再在其上使用 v-for 可以解决这个问题 (这也更加明显易读):
<template v-for="todo in todos">
  <li v-if="!todo.isComplete">
    {{ todo.name }}
  </li>
</template>

命名格式

组件命名

image.png

  • Vue 支持将模板中使用 kebab-case 的标签解析为使用 PascalCase 注册的组件。这意味着一个以 MyComponent 为名注册的组件,在模板中可以通过 <MyComponent> 或 <my-component> 引用

html里的 属性/组件命名

image.png

模板/属性绑定值的类型

  • setup里面的let/const这种声明的变量 可以直接在模板/模板标签属性 里绑定使用,只是没有响应式(ref/reactive 的才有响应式),只能是初始值
  • vue2里若变量放export default外面,是不可以在模板里用的

props

类型校验

  • 注意,使用组件时传prop,即使有类型校验,传入null/undefined 也不会报错
defineProps({ 
// 基础类型检查 
// (给出 `null` 和 `undefined` 值则会跳过任何类型检查) 
propA: Number, 
// 多种可能的类型 
propB: [String, Number],

默认值

  • 除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined。//未设置default时
  • 如果声明了 default 值,那么在 prop 的值被解析为 undefined 时,无论 prop 是未被传递还是显式指明的 undefined,都会改为 default 值。//显式指明的undefined也会取default的值(事实上,某个prop值为undefined/null时,该属性会被vue忽略,并不会真传给子组件)
  • 类型为boolean的,没传即为false,有该属性即为true

组件事件

如果一个原生事件的名字 (例如 click) 被定义在 emits 选项中,则监听器只会监听组件触发的 click 事件而不会再响应原生的 click 事件。

v-model时的修饰符(注意和自定义指令v-xx的区别)

  • 修饰符当成props
    image.png
  • 多个双向数据绑定不用.sync了
// 还是通过发送update:prop事件来更新prop绑定的值
const emit = defineEmits(['update:modelValue'])
emit('update:modelValue', value)

image.png


v3中常见功能的引用/使用模式

import { ref,reactive,nextTick,computed,onMounted,watch } from 'vue'
<button @click="$emit('increaseBy', 1)"> Increase by 1 </button>

//返回值是个proxy对象(reactive)
const props = defineProps(['title'])//js里要用时才需要变量接收返回值,若只是模板要用,不需要接收
const emit = defineEmits(['inFocus'])
emit('inFocus',arg1,arg2)

defineExpose({ a, b })//暴露组件里的变量/方法

常见的reactive

  • pinia useStore()返回的是reactive

为了从 store 中提取属性时保持其响应性,你需要使用 storeToRefs()。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上:

<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>
  • defineProps(['title']) 返回值是reactive

常见的ref

  • 一般来说,如果可能有 能直接用的基础类型的响应式的值,那么就采用的是ref
  • computed返回值是个计算属性 ref对象,需要取value值