为了开始使用Composition API,我们需要有一个可以实际使用它(编写代码)的地方;
在Vue组件中,这个位置就是 setup 函数;
◼ setup其实就是组件的另外一个选项:
只不过这个选项强大到我们可以用它来替代之前所编写的大部分其他选项;
比如methods、computed、watch、data、生命周期等等;
0.最基础的setup使用
<template>
<div class="">
<h2>message:{{message}}</h2>
</div>
</template>
<script>
export default {
setup()
{
const message="hello"
return {
message
}
}
}
</script>
<style scoped>
</style>
1.setup实现计数器
因为setup定义的数据非响应式,counter不能即时改变,所以引入了ref函数和.value属性
这里可以看到原本的method,data,computed都放在了setup内部,功能模块的实现由分散变为集中
<template>
<div class="app">
<!-- template中ref对象自动解包 -->
<h2>当前计数: {{ counter }}</h2>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
// 1.定义counter的内容
// 默认定义的数据都不是响应式数据
let counter = ref(100)
const increment = () => {
counter.value++
console.log(counter.value)
}
const decrement = () => {
counter.value--
}
return {
counter,
increment,
decrement
}
}
}
</script>
<style>
</style>
2.reactive api 实现响应式
如果想为在setup中定义的数据提供响应式的特性,那么我们可以使用reactive的函数:
◼ 那么这是什么原因呢?为什么就可以变成响应式的呢?
这是因为当我们使用reactive函数处理我们的数据之后,数据再次被使用时就会进行依赖收集;
当数据发生改变时,所有收集到的依赖都是进行对应的响应式操作(比如更新界面);
事实上,我们编写的data选项,也是在内部交给了reactive函数将其编程响应式对象的;
但是reactive不可用对应简单的数据比如单纯的counter使用,可以对对象使用
但是注意要import此函数
<template>
<div>
<h2>message: {{ message }}</h2>
<button @click="changeMessage">修改message</button>
<hr>
<h2>账号: {{ account.username }}</h2>
<h2>密码: {{ account.password }}</h2>
<button @click="changeAccount">修改账号</button>
</div>
</template>
<script>
import { reactive} from 'vue'
export default {
setup() {
let message = "Hello World"
function changeMessage() {
message = "你好啊,李银河!"
console.log(message)
}
const account = reactive({
username: "coderwhy",
password: "123456"
})
function changeAccount() {
account.username = "kobe"
}
return {
message,
changeMessage,
account,
changeAccount,
}
}
}
</script>
<style scoped>
</style>
下方使用了响应式数据,点击按钮会响应式变化,上面则不会
3.ref api实现简单数据响应式
◼ reactive API对传入的类型是有限制的,它要求我们必须传入的是一个对象或者数组类型:
如果我们传入一个基本数据类型(String、Number、Boolean)会报一个警告;
◼ 这个时候Vue3给我们提供了另外一个API:ref API
ref 会返回一个可变的响应式对象,该对象作为一个响应式的引用 维护着它内部的值,这就是ref名称的来源;
它内部的值是在ref的 value 属性中被维护的;
◼ 这里有两个注意事项:
在模板中引入ref的值时,Vue会自动帮助我们进行解包操作,所以我们并不需要在模板中通过 ref.value 的方式来使用;
但是在 setup 函数内部,它依然是一个ref引用, 所以对其进行操作时,我们依然需要使用 ref.value的方式;
<template>
<div>
<h2>当前计数: {{ counter }}</h2>
<button @click="increment">+1</button>
<button @click="counter++">+1</button>
</div>
</template>
<script>
import {ref } from 'vue'
export default {
setup() {
// 2.2.ref函数: 定义简单类型的数据(也可以定义复杂类型的数据)
// counter定义响应式数据
const counter = ref(0)
function increment() {
counter.value++
}
return {
counter,
increment,
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<h2>message: {{ message }}</h2>
<button @click="changeMessage">修改message</button>
<hr>
<h2>账号: {{ account.username }}</h2>
<h2>密码: {{ account.password }}</h2>
<button @click="changeAccount">修改账号</button>
<hr>
<!-- 默认情况下在template中使用ref时, vue会自动对其进行解包(取出其中value) -->
<h2>当前计数: {{ counter }}</h2>
<button @click="increment">+1</button>
<button @click="counter++">+1</button>
<hr>
<!-- 使用的时候不需要写.value -->
<h2>当前计数: {{ info.counter }}</h2>
<!-- 修改的时候需要写.value -->
<button @click="info.counter.value++">+1</button>
</div>
</template>
<script>
import { reactive, ref } from 'vue'
export default {
setup() {
// 1.定义普通的数据: 可以正常的被使用
// 缺点: 数据不是响应式的
let message = "Hello World"
function changeMessage() {
message = "你好啊,李银河!"
console.log(message)
}
// 2.定义响应式数据
// 2.1.reactive函数: 定义复杂类型的数据
const account = reactive({
username: "coderwhy",
password: "123456"
})
function changeAccount() {
account.username = "kobe"
}
// 2.2.ref函数: 定义简单类型的数据(也可以定义复杂类型的数据)
// counter定义响应式数据
const counter = ref(0)
function increment() {
counter.value++
}
// 3.ref是浅层解包
const info = {
counter
}
return {
message,
changeMessage,
account,
changeAccount,
counter,
increment,
info
}
}
}
</script>