加载中...

vue3的setup使用

vue3的setup使用

前言

由于在前端代码的构建当中,我们对代码的简洁易用的需求与日俱增Vue3推出的setup语法糖

setup语法糖的优势

Vue 3 的 Composition API 和 setup 语法糖带来了一些优势

相较于 Vue 2 的选项 API,它提供了更灵活和可组合的方式来组织组件逻辑。

以下是一些使用 Vue 3 setup 语法糖的好处,并与 Vue 2 进行比较的例子:

更清晰的逻辑组织

Vue 2(使用选项 API):

js
代码解读
复制代码
<script lang="js"> export default { // 数据 data() { return { count: 0, }; }, // 计算属性 computed: { doubleCount() { return this.count * 2; }, }, // 方法 methods: { increment() { this.count++; }, }, }; </script>

Vue 3(使用 setup 的传统写法,不建议):

js
代码解读
复制代码
<script lang="js"> import {computed, ref} from ''vue''; export default { setup() { // 响应式数据 const count = ref(0); // 计算属性 const doubleCount = computed(():number => count.value * 2); // 方法 const increment = (): void => { count.value++; }; // 返回组件需要的数据和方法 return { count, doubleCount, increment, }; }, }; </script> // 相对于Vue2的写法,简化的并不明显

Vue 3(setup 语法糖写法,推荐!):

js
代码解读
复制代码
<script setup lang="js"> //自动注入 import {computed, ref} from ''vue''; // 响应式数据 const count = ref(0); // 计算属性 const doubleCount = computed((): number => count.value * 2); // 方法 const increment = (): void => { count.value++; }; </script> //和Vue2以及setup传统写法相比,简化了50%的代码 <script setup> 是 Vue 3.0.0+ 中引入的新语法糖,它的目标是简化组件的写法,特别是对于那些相对简单的组件。

更好的类型推断和IDE支持

由于 setup 使用了函数的返回值来定义组件的 API,IDE 能够更好地推断类型和提供代码补全,使开发过程更加流畅。

无需导入 不需要手动导入和声明 ref、reactive 等,它会自动处理。

自动注入组件的上下文 不需要手动使用 this 访问组件上下文,变量和方法都会被自动注入到当前作用域中。

更好的类型推断 TypeScript 用户会受益于更好的类型推断,因为

更灵活的组合逻辑

Vue 3 的 Composition API 允许将相关的逻辑组合在一起,而不是按照选项 API 的生命周期来组织。

这使得代码更容易重用和维护。

下面是一个例子,展示了如何组合逻辑:

js
代码解读
复制代码
<template> <div> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> </div> </template> <script setup lang="js"> // 导入 ref 函数 import { ref } from ''vue''; // 定义组合逻辑 - 计数器 const useCounter = () => { // 响应式数据 const count = ref(0); // 方法 const increment = (): void => { count.value++; }; // 返回组合逻辑的数据和方法 return { count, increment, }; }; // 使用组合逻辑 const { count, increment } = useCounter(); </script>

更好的响应式能力

Vue 3 的响应式系统经过改进,更加高效。setup 内部的响应式数据可以更细粒度地进行管理,提高性能。

下面是一个使用

js
代码解读
复制代码
<template> <div> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> </div> </template> <script setup lang="ts"> // 导入 ref 函数 import { ref } from ''vue''; // 定义响应式数据 const count = ref(0); // 定义方法 const increment = (): void => { count.value++; }; </script>

Vue2和Vue3 setup语法糖的生命周期比较

生命周期

New Image

基本上,Vue 的每个主要生命周期事件都被分成两个钩子,分别在该事件之前和之后调用。在你的 Vue 应用中,有四个主要事件(8个主要钩子)可以利用。

创建(Creation) 在组件创建时运行

挂载(Mounting) 当 DOM 被挂载时运行

更新(Updates) 当响应式数据被修改时运行。

销毁(Destruction) 在元素被销毁之前运行

这些生命周期事件和钩子在 Vue 组件的整个生命周期中发挥着重要作用,允许你在组件的不同阶段执行代码,以适应应用的需求。

Vue2和Vue3中生命周期的对应关系

如下图所示:

New Image

setup的执行时机

在beforeCreate钩子之前执行

如下图所示:

New Image

setup函数是处于生命周期函数 beforeCreate 和 Created 两个钩子函数之前的函数

执行 setup 时,组件实例尚未被创建(在 setup() 内部,this 不会是该活跃实例的引用,即不指向vue实例,Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined)

三、setup语法糖注意事项 尽量不要与Vue2.配置混用 Vue2x配置 (data、methos、computed…) 中可以访问到setup中的属性、方法 但在setup中不能访问到Vue2.x配置(data、methos、computed…) 如果有重名,setup优先 setup函数中不能使用this Vue为了避免我们错误的使用,直接将setup函数中的this修改为undefined

setup 接受两个参数 props context(包含attrs(非props属性)、slots(插槽)、emit(事件派发)) 代码示例如下:

js
代码解读
复制代码
<template> <div> <p>Message: {{ message }}</p> <button @click="handleClick">Click me</button> </div> </template> <script setup lang="js"> // 导入 ref 函数 import { ref, defineProps, defineEmits, withDefaults } from ''vue''; // 定义 props 类型 interface MyProps { message: string; } // 定义组件逻辑 const setup = (props: MyProps, context: any) => { // 使用 defineProps 获取 props const { message } = defineProps(props); // 使用 ref 定义响应式数据 const count = ref(0); // 使用 defineEmits 获取 emit const emit = defineEmits(); // 定义方法 const handleClick = () => { count.value++; // 使用 emit 触发自定义事件 emit(''click'', count.value); }; // 返回组件需要的数据和方法 return { message, count, handleClick, }; }; </script>

在这个例子中,MyProps 接口定义了 message 属性的类型。通过 defineProps 函数,我们可以获取到正确类型的 props 对象。而通过 defineEmits 函数,我们可以获取到 emit 函数,用于在 setup 函数中派发自定义事件。

setup语法糖中和模板(Template)的双向绑定 从 setup()中返回的对象上的 property 返回并可以在模板中被访问时,它将自动展开为内部值

不需要在模板中追加 .value

代码如下图所示:

js
代码解读
复制代码
<template> <div> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> </div> </template> <script setup lang="js"> // 导入 ref 函数 import { ref } from ''vue''; // 在 setup 函数中定义响应式数据 const count = ref(0); // 在 setup 函数中定义方法 const increment = () => { count.value++; }; </script>

在这个例子中,count 是一个由 ref 创建的响应式数据,而 increment 是一个在 setup 函数中定义的方法。

它们会被自动展开为内部值,因此在模板中直接访问 count 和调用 increment 即可,无需再添加 .value。

这种简化的写法使得在模板中使用响应式数据更加直观和清晰。

setup函数只能是同步的不能是异步的 setup() 函数被设计为在组件实例被创建时同步执行的,它负责设置组件的初始状态和逻辑。

Vue 3 的组合式 API 使得在 setup() 函数中使用响应式数据、计算属性、生命周期钩子等变得更加方便和灵活。

如果您需要在组件加载后执行异步操作,您可以将异步逻辑放在 setup() 函数外部的普通函数中,并在 setup() 函数中调用该函数。

代码示例如下:

js
代码解读
复制代码
<template> <div> <p>{{ message }}</p> </div> </template> <script setup lang="js"> // 导入 ref 函数 import { ref, onMounted } from ''vue''; // 在 setup 函数中定义响应式数据 const message = ref(''''); // 错误示例:在 setup 函数中使用异步操作 // 以下代码将导致编译错误 const fetchData = async () => { const response = await fetch(''https://example.com/data''); message.value = await response.text(); }; // 正确示例:使用 onMounted 钩子来进行异步操作 // onMounted 钩子在组件挂载后执行,适合异步操作 onMounted(async () => { const response = await fetch(''https://example.com/data''); message.value = await response.text(); }); </script>

在错误的示例中,我们尝试在 setup 函数中使用异步函数 fetchData,这将导致编译错误。

相反,在正确的示例中,我们使用了 onMounted 钩子,该钩子在组件挂载后异步执行,因此适合包含异步操作