Vue3-组合式API学习之setup
- api官方文档 https://v3.cn.vuejs.org/guide/composition-api-introduction.html#setup
1.setup函数的特性以及作用
- 1、setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之间的函数 也就说在 setup函数中是无法 使用 data 和 methods 中的数据和方法的
- 2、setup函数是 Composition API(组合API)的入口
- 3、在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用
2.setup函数的注意点
- 1、由于在执行 setup函数的时候,还没有执行 Created 生命周期方法,所以在 setup 函数中,无法使用 data 和 methods 的变量和方法
- 2、由于我们不能在 setup函数中使用 data 和 methods,所以 Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined
- 3、setup函数只能是同步的不能是异步的
由于在执行 setup 时尚未创建组件实例,因此在 setup 选项中没有 this。
这意味着,除了 props 之外,你将无法访问组件中声明的任何属性——本地状态、计算属性或方法。
3.模板中使用
- 在 Vue 3.0 中,我们可以通过一个新的 ref 函数使任何响应式变量在任何地方起作用
- ref定义响应式数据(字符串、Number、bool)在setup函数中,用于创建一个响应式数据,当数据发生改变时,Vue会自动更新UI
- reactive定义响应式数据(Object、Array)
- 在 VUE 的模板中使用 ref 的值不需要通过 value 获取 (Vue 会通过自动给 ref 的值加上 .value)
- 在 js 中使用 ref 的值必须使用 .value 获取
- ref 底层的本质还是 reactive 系统会自动根据我们给 ref 传入的值将他转换成 ref(xx) —— reactive({value: xx})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28<template>
{{count}}
{{object.list}}
{{object.foo}}
<button @click="plusOne()">+</button>
</template>
<script>
import {ref,reactive} from 'vue';
export default{
setup(){
const count = ref(0)
const object = reactive({
foo:'bar',
list:['1']
})
function plusOne(){
//想改变值或获取值 必须.value
count.value++
}
return {
count,
object,
plusOne
}
},
}
</script>4.渲染函数 / JSX中使用
- setup也可以返回一个函数,函数中也能使用当前setup函数作用域中的响应式数据。
1
2
3
4
5
6
7
8
9
10
11
12
13<script>
import {h,ref,reactive} from 'vue';
export default{
setup(){
const count = ref(0);
const object = reactive({
foo:'foo'
})
return ()=> h('div',[count.value,'----',object.foo])
}
}
</script> - 3和4中,虽然都是用ref来定义count的初始值,但在使用过程中却不同,
- 直接return出去暴露给模板的不需要.value,可以自动被解开,所以直接使用即可。
- 但是h函数中,却需要count.value才能获取相应的值。
代码分割
- vue2 Options API 约定:
- 我们需要在 props 里面设置接收参数
- 我们需要在 data 里面设置变量
- 我们需要在 computed 里面设置计算属性
- 我们需要在 watch 里面设置监听属性
- 我们需要在 methods 里面设置事件方法
- 你会发现 Options APi 都约定了我们该在哪个位置做什么事,这反倒在一定程度上也强制我们进行了代码分割。
现在用 Composition API,不再这么约定了,于是乎,代码组织非常灵活,我们的控制代码写在 setup 里面即可。
setup函数提供了两个参数 props和context,
重要的是在setup函数里没有了this,在 vue3.0 中,访问他们变成以下形式: this.xxx => context.xxx
父子组件传参setup的第一个参数 props
setup中的funtion都需要key.value等于去赋值
- setup函数接收props作为其第一个参数,props对象是响应式的,watchEffect或watch会观察和响应props的更新。
- 不要…对props对象进行解构,那样会失去响应性。用toRefs对对象进行解构
- 父组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<template>
<setUpComp :data_="sendData" @name-changed=changeName></setUpComp>
<p>当前数据: {{a}}</p>
</template>
<script>
import setUpComp from './components/2.setUp父子传参'
import {ref} from 'vue'
export default {
name: 'App',
setup(){
const sendData = ref('我是父组件数据');
let a = ref('等待接收子组件数据');
function changeName(val){
a.value = val
}
return {
sendData,
changeName,
a
}
},
components: {
setUpComp
}
}
</script> - 子组件 setUpComp
- setup(props)中的props参数和props:{data_:String}相对应 否则参数找不到数据
- Context 第二个参数提供了一个上下文对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34<template>
<div class="hello">
<h3>2-setup父子传参</h3>
<p>{{propContent}}</p>
<button @click="plusOne()">触发父组件方法传参</button>
</div>
</template>
<script>
import {ref,reactive,watchEffect} from 'vue'
export default {
props:{
data_:String
},
data(){
return{
}
},
setup(props,context){
//接收父组件传递过来的数据
let propContent = ref(props.data_);
//触发父组件方法
var plusOne = () => {
context.emit('name-changed','我是子组件传递到父组件的数据')
}
//必须返回 模板中才能使用
return {
pplusOne,
propContent
}
},
}
</script>为什么props没有被包含在上下文中
- 1.组件使用props的场景更多,有时甚至只需要使用props
- 2.将props独立出来作为一个参数,可以让TypeScript对props单独做类型推导,不会和上下文中其他属性混淆。
这也使得setup、render和其他使用了TSX的函数式组件的签名保持一致。this的用法
- this在setup中不可用,方法和声明周期都可以写在setup中,如果在方法中访问setup中的变量时,直接变量名就可以使用
- 方法名和变量名要在setup中return出去才可以正常执行。