为什么使用 setup ?
-
大型组件中选项的分离掩盖了潜在的逻辑问题。此外,在处理单个逻辑关注点时,我们必须不断地“跳转”相关代码的选项块。 如果能够将同一个逻辑关注点相关代码收集在一起会更好。而这正是组合式 API 使我们能够做到的。
-
通过创建 Vue 组件,我们可以将界面中重复的部分连同其功能一起提取为可重用的代码段。然而,光靠这一点可能并不够,尤其是当你的应用变得非常大的时候,共享和重用代码变得尤为重要。
-
为了开始使用 组合式 API,我们首先需要一个可以实际使用它的地方。在 Vue 组件中,我们将此位置称为
setup
。
简单举例:
角色权限页面功能:新增/删除角色、获取角色列表、获取角色对应的权限信息、编辑角色权限信息。
- 通常以前会将这些功能写在一个sfc组件(.vue),当需要修改其中1处功能逻辑时,我们就需要跳转对应的各个options api选项进行操作。当有些业务组件复杂时,代码量上去了,浏览起来会更吃力。
- 而有了setup、composition api后,我们可以将这例子中的4个功能逻辑拆分到对应的.js文件文件,使用composition api编写业务代码,然后引入到sfc组件的setup里使用。此时我们修改其中1处功能逻辑,只需要去对应的.js文件进行修改即可,而不必被其他的功能逻辑代码干扰。
错误用法:
有些人写setup,以为是将vue2的写法,挪到setup内声明、return出去,导致setup内代码特别长,并且比options api写法更难以阅读!(当然代码量少的情况下,不影响阅读 也可不拆分)
本文章只对setup进行讲解,各个组合式api 的功能使用请查看我发的其他文章。
setup
- 类型:
Function
- setup 函数是一个新的组件选项。它是组件内部使用组合式 API 的入口点。
- 调用时间:在创建组件实例时,在初始 prop 解析之后立即调用 setup。在生命周期方面,它是在 beforeCreate 钩子之前调用的。
- template内使用:如果 setup 返回一个对象,则该对象的属性将合并到组件模板的渲染上下文中
- 请注意,从 setup 返回的 refs 在模板中访问时会自动解包,因此模板中不需要 .value。
- setup 生命周期 略 ....
- setup() 内的声明的函数、响应式数据,外部要用的话,必须 return {} 出去!
<template>
<div>{{ test }}</div>
<button @click='fn'>修改test</button>
</template>
<script lang="ts">
import { ref,onMounted,defineComponent } from 'vue'
export default defineComponent({
props: {
name: String
},
setup(props, { attrs, slots, emit, expose }) {
// console.log({ attrs, slots, emit, expose });
// attrs、slots 和 emit 分别等同于 $attrs、$slots、$emit 实例 property。
// expose 等同于 options api 的expose。
let test = ref<string>('123')
onMounted(() => {
console.log(test)
});
const fn = ()=>{
test.value = '无法预测的舞台'
}
return {
test,
fn
}
},
})
</script>
注意事项:
-
setup
内的this
是不指向组件实例的!this > undefined
-
props
对象是响应式的——即在传入新的 props 时会对其进行更新,通过使用watchEffect
或watch
进行观测和响应; -
但是,请不要解构
props
对象,因为它会失去响应式;
<script setup> 语法糖
<script setup>
是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的<script>
语法,它具有更多优势:- 更少的样板内容,更简洁的代码。
- 能够使用纯 Typescript 声明 props 和抛出事件。
- 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
- 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)。
- 功能:
- 顶层的绑定会被暴露给模板 (在 template 模板中直接使用)
- 递归组件:由于没有 options api 的 name ,如果需要使用递归组件,则使用文件名。或者再写个普通 script 标签,照旧 name:"xx"。
- 如果有2个script标签,设置为Ts的时候,2个都必须加上lang='ts'
- 动态组件:
<script setup>
动态组件写法请前往 动态组件 查看 <script setup>
: 使用<script setup>
的组件是默认关闭的,也即通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在<script setup>
中声明的绑定。- 需要使用
defineExpose()
声明需要暴露的内容。
- 需要使用
- 模板引用 ref (这个ref不是ref()响应性函数的ref)
- 变量名为模板 ref 值
- 组件通信的部分选项API 如
props
emits
expose
,在setup
中由 编译器宏 (setup
语法糖的内置方法) 提供。
QQ交流群:522976012 ,欢迎来玩。
聚焦vue3,但不限于vue,任何前端问题,究其本质,值得讨论,研究与学习。