Composition API
1.Options API的缺点
-
在Vue2的开发中,我们使用的是组合式API:
- 组合式API一大特点就是在对应属性中编写对应的功能
- 例如: data, methods,computed,watch,etc...
-
但其实这种代码有一个很大弊端
- 就是如果实现某一个功能的时候,这个功能对应的代码逻辑会被拆分到各个属性中;
- 当组件变的越大,越复杂的时候,逻辑关注点的列表会增长,那么同一个功能的逻辑就会被拆分的很分散
2.认识Composition API
-
为了开始使用Composition API,我们需要有一个可以实际使用它(编写代码)的地方
-
就在setup函数中
-
setup函数其实就是组件的另外一个选项
- 在setup函数中可以编写之前option api的大部分东西
3.setup函数的参数
-
第一个参数是props
-
第二个参数是context也可以简写为ctx上下文的意思
-
props其实很好理解,其实就是父组件传递过来的属性会放在props对象里,如果setup中如果需要使用,那么就可以通过props参数获取到传过来的值
- 对于定义props的类型,我们还是和之前的是一样的,在props选项中定义;
- 并且template中依旧能正常使用props的属性
- setup函数里面不能直接this获取props
- 因为props有直接作为参数传递到setup函数中,所以我们可以直接通过参数来使用即可
-
context也称为SetupContext,里面包含有三个属性
- attrs:所有非prop的attribute
- slots:父组件传递过来的插槽
- emit:当我们组件内部需要发出事件时会用到emit(不能使用this)
来段代码看看
- App.vue
<template>
<div>
<Home message="🥷你好"></Home>
</div>
</template>
<script>
import Home from "./Home.vue"
export default {
components: {
Home
}
setup() {
}
}
</script>
<style scoped>
</style>
- Home.vue
<template>
<div>
HOME PAGE
<h2>{{props.message}}</h2>
</div>
</template>
<script>
export default {
props: {
message: {
type:String,
required:true
}
}
setup(props,{attrs,slots,emit}) {
console.log(props.message)
console.log(context.emit) 对象结构完就不需要context.了
console.log(emit)
}
}
</script>
<style scoped>
</style>
4.setup需要返回值
- setup返回的值可以在template进行使用
- 也就是之前的data() {return {}}被替代了
- 方法和data在setup函数中都需要被返回,要不然使用不了
<template>
<div>
HOME PAGE
<h2>{{message}}</h2>
<button @click="changMessage">点我修改信息</button>
</div>
</template>
<script>
import {ref} from "vue"
export default {
setup(props,{emit}) {
const message = ref("你好") //这个ref先不要理解,知道有这么一个东西就行,后面进行说明.
//函数修改值
const changMessage = () => {
message.value = "javascript"
}
return {
message,
changMessage
}
}
}
</script>
<style scoped>
</style>
5.setup的this问题
- this并没有指向当前组件实例
- 并且setup被调用之前,data, computed,methods等都没有被解析
- 所以是没法在setup中获取this
6.Reactive API
-
reactive函数在setup函数中提供响应式的特性
-
为什么可以变成响应式?
- 是因为如果使用reactive函数给我们的数据之后,数据再次使用会进行依赖收集
- 当数据变化时,收集到的依赖都是对应的响应式操作(比如更新页面)
- 其实以前data() {}也是在内部交给了reactive函数的哦
<template>
<div>
HOME PAGE
<h2>{{person.age}}</h2>
<button @click="changPerson">点我修改信息</button>
</div>
</template>
<script>
import {reactive} from "vue"
export default {
setup(props,{emit}) {
const person = reactive({
age:21
})
const changPerson = () => {
person.age = 18
}
return {
person,
changPerson
}
}
}
</script>
<style scoped>
</style>
7.Ref API
- reactive API对传入的类型是有限制的,它要求必须传入的是一个对象或者数组类型:
- 如果我们传入一个基本数据类型会报警告;
-
那就可以使用ref,会返回一个可变的响应式对象,该对象作为一个 响应式的引用 维护着它内部的值,这就是ref名称的来源
-
这里有两个注意事项:
- 在模板中引入ref的值时,Vue会自动进行解包操作,所以并不需要在模板中通过 ref.value 的方式来使用
- 但是在 setup 函数内部,它依然是一个 ref引用, 所以对其进行操作时,所以,依然需要使用 ref.value的方式;
<template>
<div>
HOME PAGE
<h2>{{age}}</h2>
<button @click="changAge">点我修改信息</button>
</div>
</template>
<script>
import {ref} from "vue"
export default {
setup(props,{emit}) {
const age = ref(25)
const changAge = () => {
age.value = 18
}
return {
age,
changAge
}
}
}
</script>
<style scoped>
</style>
8.解包操作
- 其实ref是很浅的解包,所以如果你用另外一个对象存放声明好的ref其实是在template不会帮你解包的
- 但是在reactive是可以解包的
<template>
<div>
HOME PAGE
<h2>{{age}}</h2>
<h3>{{newrefAge.age}}</h3> <!-- 不会解包,需要再.value -->
<h4>{{newreactiveAge.age}}</h4><!-- 可以输出值 -->
<button @click="changAge">点我修改信息</button>
</div>
</template>
<script>
import {ref,reactive} from "vue"
export default {
setup(props,{emit}) {
const age = ref(25)
const changAge = () => {
age.value = 18
}
const newrefAge = {
age
}
const newreactiveAge = {
age
}
return {
age,
changAge
newrefAge
newreactiveAge
}
}
}
</script>
<style scoped>
</style>
9.readonly
- readyonly就是不能被修改,只能读取,假设把值传递给子组件的响应式对象,设置了readonly就不能被修改。
- readonly也是会返回原生对象的只读代理(但它还是一个Proxy,set方法被劫持,并且不能进行修改)
- 第一种普通对象
<template>
<button @click="updateInfo">
点我修改
</button>
</template>
<script>
import {readonly} from "vue"
export default {
setup() {
const info = {person:"周杰伦"}
const readonlyInfo = readonly(info)
const updateInfo =() => {
readonlyInfo.person = "林俊杰"
}
return {
updateInfo
}
}
}
</script>
- 响应式对象
<template>
<button @click="updateInfo">
点我修改
</button>
</template>
<script>
import {readonly,reactive} from "vue"
export default {
setup() {
const info = reactive({
person:"周杰伦"
})
const readonlyInfo = readonly(info)
const updateInfo =() => {
readonlyInfo.person = "林俊杰"
}
return {
updateInfo
}
}
}
</script>
- 响应式对象ref
<template>
<button @click="updateInfo">
点我修改
</button>
</template>
<script>
import {ref,readonly} from "vue"
export default {
setup() {
const info = ref("周杰伦")
const readonlyInfo = readonly(info)
const updateInfo =() => {
readonlyInfo.value = "林俊杰"
}
return {
updateInfo
}
}
}
</script>
[提示💡] 其实本质上就是readonly返回的对象的setter方法被劫持了而已;
10.小总结
- 这篇文章就是全面的开启了Vue3的主要新特性
- 在选项式api中的this是不能使用的,要转换习惯
- 选项式api还提供了ref和reactive响应式对象,都有对应注意的点,比如reactive只能定义复杂数据类型,简单数据类型不能定义哦
- readonly可以设置成为只读的类型,一般使用都是给子组件传递一些不修改的值🔒