目前setup sugar已经进行了定稿,vue3 + setup sugar + TS的写法看起来很香,写本文时 Vue 版本是 “^3.2.6”
新的 setup 选项是在组件创建之前, props 被解析之后执行,是组合式 API 的入口。
WARNING
在 setup 中你应该避免使用 this,因为它不会找到组件实例。setup 的调用发生在 data property、computed property 或 methods 被解析之前,所以它们无法>在 setup 中被获取。
setup 选项是一个接收 props 和 context 的函数,我们将在之后进行讨论。此外,我们将 setup 返回的所有内容都暴露给组件的其余部分 (计算属性、方法、生命周期钩子等等) 以及组件的模板。
它是 Vue3 的一个新语法糖,在 setup 函数中。所有 ES 模块导出都被认为是暴露给上下文的值,并包含在 setup() 返回对象中。相对于之前的写法,使用后,语法也变得更简单。
在添加了setup的script标签中,我们不必声明和方法,这种写法会自动将所有顶级变量、函数,均会自动暴露给模板(template)使用
这里强调一句 “暴露给模板,跟暴露给外部不是一回事”
使用方式极其简单,仅需要在 script 标签加上 setup 关键字即可。示例:
该setup功能是新的组件选项。它是组件内部暴露出所有的属性和方法的统一API。
使用后意味着,script标签内的内容相当于原本组件声明中setup()的函数体,不过也有一定的区别。
使用 script setup 语法糖,组件只需引入不用注册,属性和方法也不用返回,也不用写setup函数,也不用写export default ,甚至是自定义指令也可以在我们的template中自动获得。
创建组件实例,然后初始化 props ,紧接着就调用setup 函数。从生命周期钩子的视角来看,它会在 beforeCreate 钩子之前被调用.
如果 setup 返回一个对象,则对象的属性将会被合并到组件模板的渲染上下文
{{ count }} {{ object.foo }}
「props」 第一个参数接受一个响应式的props,这个props指向的是外部的props。如果你没有定义props选项,setup中的第一个参数将为undifined。props和vue2.x并无什么不同,仍然遵循以前的原则;
「context」 第二个参数提供了一个上下文对象,从原来 2.x 中 this 选择性地暴露了一些 property。
如果需要定义类似 name 的属性,可以再加个平级的 script 标签,在里面实现即可。
通过defineProps指定当前 props 类型,获得上下文的props对象。示例:
使用defineEmit定义当前组件含有的事件,并通过返回的上下文去执行 emit。示例:
defineProps 用来接收父组件传来的 props ; defineEmits 用来声明触发的事件。
//父组件
//子组件
信息:{{ props.foo }}
子组件通过 defineProps 接收父组件传过来的数据,子组件通过 defineEmits 定义事件发送信息给父组件
增强的props类型定义:
const props = defineProps<{
foo: string
bar?: number
}>()
const emit = defineEmit<(e: 'update' | 'delete', id: number) => void>()
不过注意,采用这种方法将无法使用props默认值。
父组件
子组件
子组件通过defineExpose暴露对象和方法
{{ state.title }}
watchEffect
用于有副作用的操作,会自动收集依赖。
和watch区别
无需区分deep,immediate,只要依赖的数据发生变化,就会调用
此时name只会在初次创建的时候进行赋值,如果中间想要改变name的值,那么需要借助composition api 中的reactive。
{{state.counter}}
使用ref也能达到我们预期的’counter’,并且在模板中,vue进行了处理,我们可以直接使用counter而不用写counter.value.
ref和reactive的关系:
ref是一个{value:‘xxxx’}的结构,value是一个reactive对象
曾经的提案中,如果需要暴露变量到模板,需要在变量前加入export声明:
js复制代码export const count = ref(0)
不过在新版的提案中,无需export声明,编译器会自动寻找模板中使用的变量,只需像下面这样简单的声明,即可在模板中使用该变量
{{counter}}
因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。
可以通过在生命周期钩子前面加上 “on” 来访问组件的生命周期钩子。官网:生命周期钩子
获取 slots 和 attrs
注:useContext API 被弃用,取而代之的是更加细分的 api。
可以通过useContext从上下文中获取 slots 和 attrs。不过提案在正式通过后,废除了这个语法,被拆分成了useAttrs和useSlots。
useAttrs:见名知意,这是用来获取 attrs 数据,但是这和 vue2 不同,里面包含了 class、属性、方法。
const attrs = useAttrs();
// 新
其他 Hook Api
传统的写法,我们可以在父组件中,通过 ref 实例的方式去访问子组件的内容,但在 script setup 中,该方法就不能用了,setup 相当于是一个闭包,除了内部的 template模板,谁都不能访问内部的数据和方法。
如果需要对外暴露 setup 中的数据和方法,需要使用 defineExpose API。示例:
const a = 1
const b = ref(2)
defineExpose({ a, b, })
注意:目前发现defineExpose暴露出去的属性以及方法都是 unknown 类型,如果有修正类型的方法,欢迎评论区补充。
//父组件
//子组件
妾身{{ msg }}
一、父组件调用子组件方法
子组件需要使用defineExpose对外暴露方法,父组件才可以调用。
子组件
子组件
父组件
参考网址:cn.vuejs.org/api/sfc-scr…
这可能是带来的较大便利之一,在以往的写法中,定义数据和方法,都需要在结尾 return 出去,才能在模板中使用。在 script setup 中,定义的属性和方法无需返回,可以直接使用!示例:
My name is {{name}}
注意在vue3的源代码中,setup执行完毕,函数 getCurrentInstance 内部的有个值会释放对 currentInstance 的引用,await 语句会导致后续代码进入异步执行的情况。所以上述例子中最后一个 getCurrentInstance() 会返回 null,建议使用变量保存第一个 getCurrentInstance() 返回的引用.
另外,await 的表达式会自动编译成在 await 之后保留当前组件实例上下文的格式。
注意
> async setup() 必须与 Suspense 组合使用,Suspense 目前还是处于实验阶段的特性。我们打算在将来的某个发布版本中开发完成并提供文档 - 如果你现在感兴趣,可以参照 tests 看它是如何工作的。
## 定义组件其他配置
配置项的缺失,有时候我们需要更改组件选项,在setup中我们目前是无法做到的。我们需要在上方再引入一个 script,在上方写入对应的 export即可,需要单开一个 script。