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的返回值相同
- 若ref一个基础类型,返回对象的value属性为该基础类型的值
动态参数值的限制
动态参数中表达式的值应当是一个字符串,或者是 null。特殊值 null 意为显式移除该绑定。其他非字符串的值会触发警告。
模板里的值非原始data时的方案对比
- {{methodes(data)}},通过调用方法的返回值来展示,绑定在表达式中的方法在组件每次更新时都会被重新调用
- 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>
命名格式
组件命名
- Vue 支持将模板中使用 kebab-case 的标签解析为使用 PascalCase 注册的组件。这意味着一个以
MyComponent为名注册的组件,在模板中可以通过<MyComponent>或<my-component>引用
html里的 属性/组件命名
模板/属性绑定值的类型
- 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
- 多个双向数据绑定不用.sync了
// 还是通过发送update:prop事件来更新prop绑定的值
const emit = defineEmits(['update:modelValue'])
emit('update:modelValue', value)
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值