一、API风格
Vue 的组件可以按两种不同的风格书写:选项式 API 和组合式 API。
二、组合式API
1.(组合式 API 的核心思想是直接在函数作用域内定义响应式状态变量,并将从多个函数中得到的状态组合起来处理复杂问题。这种形式更加自由,)
2.在单文件组件中,组合式 API 通常会与 <script setup> 搭配使用
3.setup 告诉 Vue 需要在编译时进行一些处理
4.实例
<script setup>
import { ref, onMounted } from 'vue'
// 响应式状态
const count = ref(0)
// 用来修改状态、触发更新的函数
function increment() {
count.value++
}
// 生命周期钩子
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
三、修复符.prevent
.prevent
修饰符会告知 v-on
指令对触发的事件调用 event.preventDefault()
<form @submit.prevent="onSubmit">...</form>
四、声明响应式状态
(1) ref() 在组合式 API 中,推荐使用 ref() 函数来声明响应式状态:
import { ref } from 'vue'
const count = ref(0)
ref()
接收参数,并将其包裹在一个带有 .value
属性的 ref 对象中返回:
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
(2)要在组件模板中访问 ref,请从组件的 setup()
函数中声明并返回它们。
注意,在模板中使用 ref 时,我们不需要附加 .value
。
对于更复杂的逻辑,我们可以在同一作用域内声明更改 ref 的函数,并将它们作为方法与状态一起公开:
<button @click="increment">
{{ count }}
</button>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
function increment() {
// 在 JavaScript 中需要 .value
count.value++
}
// 不要忘记同时暴露 increment 函数
return {
count,
increment
}
}
}
(3) <script setup>
在 setup()
函数中手动暴露大量的状态和方法非常繁琐,我们可以使用 <script setup>
来大幅度地简化代码:
<script setup>
中的顶层的导入、声明的变量和函数可在同一组件的模板中直接使用
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">
{{ count }}
</button>
</template>
(4)为什么要使用 ref?
当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。该 .value
属性给予了 Vue 一个机会来检测 ref 何时被访问或修改
(5)DOM 更新时机
要等待 DOM 更新完成后再执行额外的代码,可以使用 nextTick() 全局 API:
import { nextTick } from 'vue'
async function increment() {
count.value++
await nextTick()
// 现在 DOM 已经更新了
}
(6)reactive()
reactive()
API。与将内部值包装在特殊对象中的 ref 不同,reactive()
将使对象本身具有响应性:
import { reactive } from 'vue'
const state = reactive({ count: 0 })
(7)reactive()的局限性
1.有限的值类型,只能用于对象类型(数组、对象、map set这样的集合)
2.不能替换整个对象。这意味着我们不能轻易地“替换”响应式对象
3.对解构操作不友好
由于这些限制,我们建议使用 ref()
作为声明响应式状态的主要 API。
五、计算属性
计算属性值会基于其响应式依赖被缓存
(1)计算属性来描述依赖响应式状态的复杂逻辑
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
// 一个计算属性 ref
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
</script>
<template>
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</template>
(2)可写计算属性
计算属性默认是只读的。你可以通过同时提供 getter 和 setter 来创建
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
// getter
get() {
return firstName.value + ' ' + lastName.value
},
// setter
set(newValue) {
// 注意:我们这里使用的是解构赋值语法
[firstName.value, lastName.value] = newValue.split(' ')
}
})
</script>
现在当你再运行 fullName.value = 'John Doe'
时,setter 会被调用而 firstName
和 lastName
会随之更新。
六、按键修饰符
1. 仅在 `key` 为 `Enter` 时调用 `submit`
<input @keyup.enter="submit" />
你可以直接使用 KeyboardEvent.key 暴露的按键名称作为修饰符
<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />
<!-- Ctrl + 点击 -->
<div @click.ctrl="doSomething">Do something</div>
2.exact
修饰符 允许控制触发一个事件所需的确定组合的系统按键修饰符。
<!-- 当按下 Ctrl 时,即使同时按下 Alt 或 Shift 也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 仅当按下 Ctrl 且未按任何其他键时才会触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 仅当没有按下任何系统按键时触发 -->
<button @click.exact="onClick">A</button>
七、表单输入修饰符
1.lazy
修饰符来改为在每次 change
事件后更新数据:
<!-- 在 "change" 事件后同步更新而不是 "input" -->
<input v-model.lazy="msg" />
2.number
如果你想让用户输入自动转换为数字
3.trim
默认自动去除用户输入内容中两端的空格
八、生命周期钩子
1.onBeforeMount()
在组件被挂载之前被调用。
2.onMounted
钩子
可以用来在组件完成初始渲染并创建 DOM 节点后运行代码:
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
console.log(`the component is now mounted.`)
})
</script>
3.onBeforeUnmount()
在组件实例被卸载之前调用。
4.onUnmounted()
在组件实例被卸载之后调用。
5.onBeforeUpdate()
组件即将因为响应式状态变更而更新其 DOM 树之前调用。
6.onUpdated()
在组件因为响应式状态变更而更新其 DOM 树之后调用
7.onErrorCaptured()
在捕获了后代组件传递的错误时调用。
8.onRenderTracked()
当组件渲染过程中追踪到响应式依赖时调用,这个钩子仅在开发模式下可用,且在服务器端渲染期间不会被调用。
9.onRenderTriggered()
当响应式依赖的变更触发了组件渲染时调用。这个钩子仅在开发模式下可用,且在服务器端渲染期间不会被调用
10.onActivated()
当组件被插入到 DOM 中时调用。
11.onDeactivated()
当组件从 DOM 中被移除时调用。
12.onServerPrefetch()
注册一个异步函数,在组件实例在服务器上被渲染之前调用
onServerPrefetch(async () => {
// 组件作为初始请求的一部分被渲染
// 在服务器上预抓取数据,因为它比在客户端上更快。
data.value = await fetchOnServer(/* ... */)
})
九、依赖注入
1.provide()-提供一个值,可以被后代组件注入。
provide()
必须在组件的 setup()
阶段同步调用。
provide()
接受两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,第二个参数是要注入的值。
<script setup>
import { ref, provide } from 'vue'
import { fooSymbol } from './injectionSymbols'
// 提供静态值
provide('foo', 'bar')
// 提供响应式的值
const count = ref(0)
provide('count', count)
// 提供时将 Symbol 作为 key
provide(fooSymbol, count)
</script>
2.inject()
注入一个由祖先组件或整个应用 (通过 app.provide()
) 提供的值。