在 Vue 3 中,setup
函数的写法有两种主要方式:一种是使用 <script setup>
标签,另一种是写在 export default
对象中作为 setup
函数。它们之间的区别如下:
<script setup>
标签
-
位置 :使用
<script setup>
标签来编写setup
函数。 -
作用 :是 Vue 3 的 Composition API 的一种语法糖,简化了
setup
函数的使用。 -
优点:
- 简化语法 : 省去了显式地定义
setup
函数,代码更简洁。 - 更好支持 TypeScript: 更好的类型推断和更简洁的 TypeScript 支持。
- 自动导入: 可以自动导入一些 Vue 内置的 API 和自定义的组件、函数等。
vue<template> <div>{{ message }}</div> </template> <script setup> import { ref } from 'vue'; const message = ref('Hello Vue 3!'); </script>
- 简化语法 : 省去了显式地定义
-
注意 :此写法,
defineProps
和defineEmits
是自动使用,无需显式导入
export default
对象中的 setup
函数
-
位置 :在
export default
对象中定义setup
函数。 -
作用 :这种方式是 Vue 3 提供的标准方式,允许在对象中定义
setup
方法。 -
优点:
- 与 Options API 兼容: 适用于需要结合使用 Composition API 和 Options API 的情况。
- 传统方式: 适合于逐步迁移旧代码或与传统 Vue 2.x 的 Options API 结合使用。
vue<template> <div>{{ message }}</div> </template> <script> import { ref } from 'vue'; export default { setup() { const message = ref('Hello Vue 3!'); return { message }; } } </script>
总结
<script setup>
: 更简洁、易读,适合新开发的 Vue 3 组件和更复杂的逻辑组织。export default
对象中的setup
: 更兼容旧有代码和 Options API,适合需要逐步迁移的项目。
声明变量
-
ref
-
适用场景:主要用于定义单一的基本类型(如字符串、数字、布尔值)或对非响应式对象的包装。它也适用于创建响应式的引用类型数据(浅层响应式)。
-
使用方法 :创建一个包含
.value
属性的响应式对象,你需要通过.value
来访问和修改其值。 -
示例:
vue<template> <div>{{ count }}</div> <button @click="increment">Increment</button> </template> <script setup> import { ref } from 'vue'; // 创建一个响应式的基本类型变量 const count = ref(0); // 修改变量值 function increment() { count.value++; } </script>
-
-
reactive:
-
适用场景 :用于创建一个深度响应式的对象。它主要用于处理复杂的数据结构,如嵌套对象和数组。
reactive
会对对象的所有嵌套属性进行响应式处理。 -
使用方法 :使用
reactive
创建的对象本身就是响应式的,你可以直接访问和修改对象的属性,而不需要通过.value
。 -
示例:
vue<template> <div>{{ user.name }}</div> <button @click="updateName">Change Name</button> </template> <script setup> import { reactive } from 'vue'; // 创建一个响应式的对象 const user = reactive({ name: 'John Doe' }); // 修改对象属性 function updateName() { user.name = 'Jane Doe'; } </script>
-
计算属性
-
基本用法:用来进行数据的衍生计算。
vue<template> <div> <p>Count: {{ count }}</p> <p>Doubled Count: {{ doubledCount }}</p> <button @click="count++">Increment</button> </div> </template> <script> import { ref, computed } from 'vue'; export default { setup() { const count = ref(0); // 定义计算属性 const doubledCount = computed(() => count.value * 2); return { count, doubledCount }; } }; </script>
-
特性:
-
响应式:计算属性会自动依赖其内部使用的数据,并且在这些数据发生变化时会重新计算。Vue 会智能地缓存计算属性的值,直到它的依赖数据发生变化。
-
只读:默认情况下,计算属性是只读的。如果你需要计算属性具有 setter(写入)功能,可以提供一个对象的形式来定义计算属性,如下所示:
jsimport { ref, computed } from 'vue'; export default { setup() { const count = ref(0); // 定义具有 getter 和 setter 的计算属性 const doubledCount = computed({ get: () => count.value * 2, set: (newValue) => { count.value = newValue / 2; } }); return { count, doubledCount }; } };
-
生命周期钩子函数
onBeforeMount
-
用途: 在组件挂载之前被调用。此钩子在模板编译完成但尚未挂载到 DOM 上时触发。
-
函数签名:
jsimport { onBeforeMount } from 'vue'; onBeforeMount(() => { console.log('Component is about to mount'); });
onMounted
-
用途: 在组件挂载到 DOM 后调用。用于访问 DOM 元素或执行需要在 DOM 渲染后才能完成的操作。
-
函数签名:
jsimport { onMounted } from 'vue'; onMounted(() => { console.log('Component has been mounted'); });
onBeforeUpdate
-
用途: 在组件更新之前被调用。此钩子在组件的数据发生变化并将要重新渲染时触发。
-
函数签名:
jsimport { onBeforeUpdate } from 'vue'; onBeforeUpdate(() => { console.log('Component is about to update'); });
onUpdated
-
用途: 在组件更新之后调用。用于处理更新后的逻辑或与新的 DOM 状态相关的操作。
-
函数签名:
jsimport { onUpdated } from 'vue'; onUpdated(() => { console.log('Component has been updated'); });
onBeforeUnmount
-
用途: 在组件卸载之前被调用。用于清理资源或移除事件监听器等操作。
-
函数签名:
jsimport { onBeforeUnmount } from 'vue'; onBeforeUnmount(() => { console.log('Component is about to unmount'); });
onUnmounted
-
用途: 在组件卸载后调用。用于执行卸载后需要完成的操作,如清理外部资源或停止定时器。
-
函数签名:
jsimport { onUnmounted } from 'vue'; onUnmounted(() => { console.log('Component has been unmounted'); });
onErrorCaptured
-
用途: 当组件的子组件发生错误时调用。可以用于捕获错误并处理它们。
-
函数签名:
jsimport { onErrorCaptured } from 'vue'; onErrorCaptured((error, instance, info) => { console.error('Error captured:', error); return false; // 如果返回 false,错误不会被进一步处理 });
onActivated
-
用途 : 当组件被激活时调用。主要用于
<keep-alive>
包裹的组件,组件从缓存中激活时触发。 -
函数签名:
jsimport { onActivated } from 'vue'; onActivated(() => { console.log('Component has been activated'); });
onDeactivated
-
用途 : 当组件被停用时调用。主要用于
<keep-alive>
包裹的组件,组件被缓存时触发。 -
函数签名:
jsimport { onDeactivated } from 'vue'; onDeactivated(() => { console.log('Component has been deactivated'); });
响应式属性监听
-
watch
-
作用 :一个用于监听数据变化并执行回调函数的 API。可以用于监视响应式数据的变化、执行副作用操作或处理复杂的逻辑。提供了更灵活的方式来处理数据变化,与计算属性 (
computed
) 的响应性相比,watch
更适合处理需要副作用的场景。 -
基本用法:
-
允许你观察一个或多个响应式数据源,并在这些数据源发生变化时执行回调函数
jsimport { ref, watch } from 'vue'; export default { setup() { const count = ref(0); // 监视 `count` 的变化 watch(count, (newValue, oldValue) => { console.log(`Count changed from ${oldValue} to ${newValue}`); }); const info = reactive({ name: 'dfc' }); // 监视 `name` 的变化 watch(() => info.name, (newName, oldName) => { console.log(`info.name changed from ${oldName} to ${newName}`); }) return { count }; } };
jsimport { ref, watch, toRefs } from 'vue'; export default { setup() { const count = ref(0); const name = ref('Alice'); // 监视多个数据源 watch([count, name], ([newCount, newName], [oldCount, oldName]) => { console.log(`Count changed from ${oldCount} to ${newCount}`); console.log(`Name changed from ${oldName} to ${newName}`); }); const info = reactive({ name: 'dfc', age: 12, }); // 监视多个数据源 watch([() => info.name, () => info.age], ([newName, oldName], [newAge, oldAge]) => { console.log(`info.name changed from ${oldName} to ${newName}`); console.log(`info.age changed from ${oldAge} to ${newAge}`); }); return { count, name, info, // ...toRefs(info) }; } };
-
-
其他特性:
-
深度监视 :需要深度监视对象的嵌套属性,可以使用
deep
选项jsimport { ref, watch } from 'vue'; export default { setup() { const user = ref({ name: 'Alice', age: 30 }); // 深度监视 `user` 对象 watch(user, (newValue, oldValue) => { console.log('User object changed:', newValue); }, { deep: true }); return { user }; } };
-
立即执行 :初始化时立即执行一次回调,可以使用
immediate
选项jsimport { ref, watch } from 'vue'; export default { setup() { const count = ref(0); // 立即执行回调 watch(count, (newValue, oldValue) => { console.log(`Count changed from ${oldValue} to ${newValue}`); }, { immediate: true }); return { count }; } };
-
停止监听 :需要在某些条件下停止监听,可以使用
watch
函数返回的停止函数jsimport { ref, watch } from 'vue'; export default { setup() { const count = ref(0); const stopWatch = watch(count, (newValue, oldValue) => { console.log(`Count changed from ${oldValue} to ${newValue}`); }); // 停止监听 setTimeout(() => { stopWatch(); console.log('Stopped watching count'); }, 5000); return { count }; } };
-
-
-
watchEffect
-
作用 :一个用于自动追踪响应式数据并执行副作用的 API。它与
watch
不同,因为watchEffect
不需要明确地指定要观察的数据源,而是自动追踪函数内部使用的所有响应式数据。这使得watchEffect
更加简洁和直观,特别是当你不需要对数据变化做复杂的处理时。 -
基本用法:
jsimport { ref, watchEffect } from 'vue'; export default { setup() { const count = ref(0); // 使用 watchEffect 追踪 count 的变化 watchEffect(() => { console.log(`Count is: ${count.value}`); }); // 修改 count 的值 setTimeout(() => { count.value = 1; }, 1000); return { count }; } };
-
处理副作用 :
watchEffect
主要用于处理副作用,如更新 DOM、发送网络请求等。它在数据源变化时会重新执行回调函数,因此非常适合处理那些与数据变化有关的操作。 -
停止追踪
jsimport { ref, watchEffect } from 'vue'; export default { setup() { const count = ref(0); // 使用 watchEffect 追踪 count 的变化 const stop = watchEffect(() => { console.log(`Count is: ${count.value}`); }); // 停止追踪 setTimeout(() => { stop(); console.log('Stopped watching count'); }, 5000); return { count }; } };
与
watch
的对比watchEffect
和watch
都可以用来处理响应式数据的变化,但它们的使用场景和方式有所不同:watchEffect
: 自动追踪函数内所有响应式数据的变化,适合处理简单的副作用,不需要手动指定数据源。watch
: 需要明确指定要观察的数据源,适合处理更复杂的逻辑和副作用,允许对数据源变化进行更细粒度的控制。
深度追踪
jsimport { ref, watch } from 'vue'; export default { setup() { const user = ref({ name: 'Alice', age: 30 }); // 使用 watch 进行深度追踪 watch(user, (newValue, oldValue) => { console.log('User object changed:', newValue); }, { deep: true }); return { user }; } };
-
内置组件
Teleport
-
作用:允许你将子组件的渲染内容"传送"到 DOM 中的不同位置
-
示例:
vue// teleport 将模态框渲染到 body 元素中,而不是其父组件的 DOM 结构中 <template> <div> <button @click="showModal = !showModal">Toggle Modal</button> <teleport to="body"> <div v-if="showModal" class="modal"> <p>This is a modal!</p> <button @click="showModal = false">Close</button> </div> </teleport> </div> </template> <script> import { ref } from 'vue'; export default { setup() { const showModal = ref(false); return { showModal }; } }; </script> <style> .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; } </style>
Suspense
-
作用:用于处理异步组件的加载过程,它可以在组件异步加载时显示一个加载状态。这个功能非常适合在渲染异步数据或组件时提供用户反馈。
-
示例:
vue// Suspense 组件会在 AsyncComponent 加载时显示一个"Loading..."的文本,直到异步组件加载完成。 <template> <suspense> <template #default> <AsyncComponent /> </template> <template #fallback> <p>Loading...</p> </template> </suspense> </template> <script> import { defineAsyncComponent } from 'vue'; const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue')); export default { components: { AsyncComponent } }; </script>
Fragment
-
作用:支持多个根节点的功能,它允许一个组件返回多个根元素,而不需要额外的包裹元素。这个功能可以简化组件结构,避免不必要的 DOM 节点。
-
示例:
vue<template> <div></div> <p>First element</p> <p>Second element</p> </template> <script> export default { setup() { return {}; } }; </script>
在Vue3中使用Fragment只需要在模板中使用
template
标签包裹多个根节点即可。
组件通信
异步组件
-
defineAsyncComponent
-
作用:用于定义异步组件的函数,允许你动态地加载组件,通常用于按需加载,以提高应用的性能和响应速度。
-
示例:
js// 定义一个异步组件 AsyncComponent,它会在组件需要被渲染时才会被动态加载。 import { defineAsyncComponent } from 'vue'; const AsyncComponent = defineAsyncComponent(() => import('./MyAsyncComponent.vue') ); export default { components: { AsyncComponent } };
-
配置选项:
选项 是否必填 含义 loader 是 返回一个 Promise,Promise 解析为异步组件 loadingComponent 否 指定一个加载中组件,在异步组件正在加载时显示 errorComponent 否 指定一个错误组件,如果异步组件加载失败时显示 delay 否 指定加载组件的延迟时间(以毫秒为单位) timeout 否 指定加载组件的超时时间(以毫秒为单位) -
完整示例:
js// AsyncComponent 将在加载时显示一个"Loading..."组件,如果加载失败,则显示一个错误组件。如果异步组件的加载超过了 10 秒,则会显示错误组件。 import { defineAsyncComponent } from 'vue'; // 定义异步组件,带有加载、错误处理和延迟配置 const AsyncComponent = defineAsyncComponent({ loader: () => import('./MyAsyncComponent.vue'), loadingComponent: { template: '<div>Loading...</div>' }, errorComponent: { template: '<div>Error loading component</div>' }, delay: 200, // 200ms 延迟显示 loadingComponent timeout: 10000 // 10秒超时 }); export default { components: { AsyncComponent } };
-
Vueuse(工具函数)
-
介绍:用于 Vue 3 的工具库,提供了一系列有用的 Composition API 组合函数,帮助开发者更高效地处理常见任务。它通过简化状态管理、响应式数据和副作用的处理,提高了开发效率。
-
主要功能:
- 状态管理 :如
useLocalStorage
和useSessionStorage
让状态在浏览器存储中持久化。 - 副作用 :如
useFetch
用于进行 HTTP 请求,useInterval
和useTimeout
用于定时任务。 - 事件处理 :如
useEventListener
用于添加和移除事件监听器。 - 响应式数据 :如
useDark
处理暗黑模式,useMouse
跟踪鼠标位置。
- 状态管理 :如
-
安装与使用
-
安装
jsnpm install @vueuse/core
-
使用
js// 使用 useLocalStorage 管理本地存储: <template> <input v-model="name" placeholder="Enter your name" /> </template> <script lang="ts"> import { useLocalStorage } from '@vueuse/core'; export default { setup() { const name = useLocalStorage('name', ''); return { name }; } }; </script>
-