vue3 组合式 API:setup()

查看vue3官网介绍:组合式 API:setup()

在 Vue 3 中,组合式 API 的 setup() 函数是一个非常重要的特性,它提供了一种更灵活和可维护的方式来组织组件的逻辑。

基本概念

setup() 函数是在组件实例创建之前执行的,它用于组合组件的逻辑,包括响应式数据、方法、计算属性、监听等。它接收两个参数:propscontext,并返回一个对象,其中包含可以在组件模板中使用的属性和方法。

特点

  • setup函数返回的对象中的内容,可直接在模板中使用。
  • setup中访问thisundefined
  • setup函数会在beforeCreate之前调用,它是"领先"所有钩子执行的。

示例:

html 复制代码
<template>
  <div>
    <div>姓名:{{name}}</div>
    <div>年龄:{{age}}</div>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
  </div>
</template>
<script lang="ts">
export default {
  name: 'Person',
  setup() {
  	console.log(this);  // undefined
    // 数据(在setup中直接声明变量,此时的name、age、tel都不是响应式的数据)
    // 注意:直接声明变量,数据不是响应式的。
    let name = '张三'
    let age = 36

    // 方法
    function changeName() {
      console.log('change name')
      name = 'John'  // 这样修改name,页面是不会响应的
      console.log('changed name: ' + name); // changed name: John
      //  成功修改 name ,但是页面没有响应
    }
    function changeAge() {
      age--
      console.log(age);
      // 成功修改 age ,但是页面没有响应
    }
    // 将数据、方法暴露出去,模板中才可以使用
    return { name, age, changeName, changeAge}
  }
}
</script>

setup函数的返回值

  • 若返回一个对象:则对象中的:属性、方法等,在模板中均可以直接使用。
  • 若返回一个函数:则可以自定义渲染内容。代码如下:
javascript 复制代码
// 不论页面模板是什么样,直接渲染返回的内容
setup(){
  return ()=> 'vue3起飞!'
}

与选项式API的区别

  • setup 与 选项式API可以在vue3项目中同时存在。
  • 选项式API(如 datamethodscomputed 等)中可以访问到 setup中的属性、方法。
    但在setup中不能访问到选项式API(如 datamethodscomputed 等)。
    • 在选项式 API 中可以访问到 setup 中定义的属性和方法,这是因为 Vue 在处理组件时,会先执行 setup 函数,然后将其返回值与选项式 API 的内容进行合并,最终形成组件的实例。
    • setup 函数中不能直接访问选项式 API(如 datamethodscomputed 等),这是因为 setup 函数在组件实例创建之前执行,此时选项式 API 的内容还未被处理和合并到组件实例中。
  • 如果与选项式API冲突,则setup优先。
    • setup 的执行优先级更高,setup 返回的属性会覆盖选项式 API 中同名的属性。

示例:

javascript 复制代码
<template>
  <div>
    <div>姓名:{{name}}</div>
    <div>年龄:{{age}}</div>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>

    <br />

    <div>选项式API data 里的数据:{{ otherName }}</div>
    <div>选项式API data 里读取setup函数中声明的变量: {{ setupName }}</div>
    <button @click="handleShow">选项式API methods 定义的方法:点击显示消息</button>
  </div>
</template>
<script lang="ts">
export default {
  name: 'Person',
  data() {
    return {
      otherName: '李四',
      setupName: this.name
    }
  },
  methods: {
    handleShow() {
      alert('点击了啊啊啊啊啊')
    }
  },
  setup() {
  	console.log(this);  // undefined
    // 数据(在setup中直接声明变量,此时的name、age、tel都不是响应式的数据)
    // 注意:直接声明变量,数据不是响应式的。
    let name = '张三'
    let age = 36

    // 方法
    function changeName() {
      console.log('change name')
      name = 'John'  // 这样修改name,页面是不会响应的
      console.log('changed name: ' + name); // changed name: John
      //  成功修改 name ,但是页面没有响应
    }
    function changeAge() {
      age--
      console.log(age);
      // 成功修改 age ,但是页面没有响应
    }
    // 将数据、方法暴露出去,模板中才可以使用
    return { name, age, changeName, changeAge}
  }
}
</script>

与传统的选项式 API(如 datamethodscomputed 等)相比,组合式 API 更加灵活和可组合。它允许将相关的逻辑封装在函数中,提高了代码的复用性和可读性。同时,组合式 API 也更好地支持 TypeScript,提供了更好的类型推断和代码提示。

setup 语法糖

在 Vue 3 中,<script setup>是一种语法糖,它极大地简化了组合式 API 的使用方式。

<script setup>语法糖,可以把setup独立出去:

在 Vue 组件中,使用<script setup>标签来代替传统的<script>标签。

<script setup>中,不需要使用传统的export default语法来包裹组件的逻辑。可以直接定义响应式数据、计算属性、方法等,并且这些定义会自动暴露给模板使用 (不需要return语句来暴露数据、方法)。

把上面例子中的setup函数改为<script setup>语法糖:

typescript 复制代码
<script setup lang="ts">
console.log(this) // undefined
// 数据(在setup中直接声明变量,此时的name、age、tel都不是响应式的数据)
// 注意:直接声明变量,数据不是响应式的。
let name = '张三'
let age = 36

// 方法
function changeName() {
  console.log('change name')
  name = 'John' // 这样修改name,页面是不会响应的
  console.log('changed name: ' + name) // changed name: John
  //  成功修改 name ,但是页面没有响应
}
function changeAge() {
  age--
  console.log(age)
  // 成功修改 age ,但是页面没有响应
}
</script>

注意:用<script setup>改写setup函数后,现在有两个 <script> 标签:

  • 一个用于使用组合式 API 的 <script setup>
  • 一个用于传统的选项式 API 和组件配置:
javascript 复制代码
<script lang="ts">
export default {
  name: 'Person'
}
</script>

这个<script> 标签目前只用来配置组件的名称。

是否可以在<script setup>标签上写组件的名称呢?

插件vite-plugin-vue-setup-extend

vite-plugin-vue-setup-extend是一个用于增强 Vue 3 在 Vite 项目中使用<script setup>语法的插件。

插件vite-plugin-vue-setup-extend 中,有更详细的用法示例。

安装插件:

javascript 复制代码
npm i vite-plugin-vue-setup-extend -D

vite.config.js文件中,引入并使用该插件:

javascript 复制代码
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    VueSetupExtend(),
  ]
})

修改<script setup>标签:

javascript 复制代码
<script setup lang="ts" name="Person">
<script>

参数介绍

setup() 函数接收两个参数:propscontext:

  • props:包含了父组件传递给当前组件的属性。可以通过解构赋值的方式获取特定的属性。
  • context:包含了一些与组件相关的上下文信息,如 attrsslotsemit 等。可以通过解构赋值的方式获取特定的上下文信息。

示例:

html 复制代码
<script setup lang="ts">
// defineProps 用于定义组件接收的父组件传递过来的属性(props)。
// defineExpose 用于明确指定哪些属性和方法可以在组件外部被访问。
import { defineProps, defineExpose } from 'vue';

// 定义props
// 通过 defineProps 返回的对象可以访问到父组件传递过来的这个属性的值。
const props = defineProps({
  message: String
});

console.log(props.message);

// defineEmits 用于定义组件可以触发的自定义事件。
// 这里定义了一个名为 customEvent 的自定义事件。
const emit = defineEmits(['customEvent']);

// customMethod 是一个方法,当这个方法被调用时,
// 会触发 customEvent 事件,并传递 'some data' 作为事件参数。
const customMethod = () => {
  emit('customEvent', 'some data');
};

// 通过 defineExpose 指定了组件外部可以访问的内容。
// 这里只暴露了 customMethod 方法,在父组件或者其他组件中可以调用这个方法,
// 但不能直接访问组件内部的其他未暴露的属性和方法。
defineExpose({
  customMethod
});
</script>

返回值

  1. 响应式数据 :可以在 setup() 函数中使用 refreactive 函数来创建响应式数据。这些数据可以在组件模板中使用,并且会自动更新视图。

示例:

html 复制代码
<template>
   <div>
     <p>Count: {{ count }}</p>
     <button @click="increment">Increment</button>
   </div>
</template>
<script setup lang="ts">
 import { ref } from 'vue';

 const count = ref(0);

 const increment = () => {
   count.value++;
 };
 </script>
  1. 计算属性 :可以在 setup() 函数中使用 computed 函数来创建计算属性。计算属性是基于响应式数据计算得到的值,并且会自动更新。

示例:

javascript 复制代码
<template>
  <div>
    <p>Full Name: {{ fullName }}</p>
  </div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';

const firstName = ref('John');
const lastName = ref('Doe');

const fullName = computed(() => `${firstName.value} ${lastName.value}`);
</script>
  1. 方法 :可以在 setup() 函数中定义普通的函数,这些函数可以在组件模板中使用。

示例:

html 复制代码
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="decrement">Decrement</button>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue';

const count = ref(0);

const increment = () => {
  count.value++;
};

const decrement = () => {
  count.value--;
};
</script>
相关推荐
jerrywus几秒前
为什么每个程序员都应该试试 cmux:AI 加持的终端效率革命
前端·人工智能·claude
codeniu6 分钟前
@logicflow/vue-node-registry 在 Vite 中无法解析的踩坑记录与解决方案
前端·javascript
孟祥_成都13 分钟前
AI 术语满天飞?90% 的人只懂名词,不懂为什么!
前端·人工智能
Lupino40 分钟前
被 React “玩弄”的 24 小时:为了修一个不存在的 Bug,我给大模型送了顿火锅钱
前端·react.js
米丘1 小时前
了解 Javascript 模块化,更好地掌握 Vite 、Webpack、Rollup 等打包工具
前端
Heo1 小时前
深入 React19 Diff 算法
前端·javascript·面试
滕青山1 小时前
个人所得税计算器 在线工具核心JS实现
前端·javascript·vue.js
小怪点点1 小时前
手写promise
前端·promise
国思RDIF框架1 小时前
RDIFramework.NET Web 敏捷开发框架 V6.3 发布 (.NET8+、Framework 双引擎)
前端
颜酱1 小时前
从0到1实现LFU缓存:思路拆解+代码落地
javascript·后端·算法