组合式 API
概述
组合式API用于集中管理页面中的逻辑代码,使页面中的 data、method 等集中在一处,避免相同业务的代码散落在页面的不同部位;
示例
如下,通过vue2, vue3两种形式实现同一个需求;
两个独立的功能:
- 通过点击按钮来控制div的显示和隐藏
- 通过点击按钮控制div内字体颜色的变化
Vue2实现
<template>
<div>
<!-- 功能一模板 -->
<button @click="show">显示</button>
<button @click="hide">隐藏</button>
<div class="box" v-if="showDiv">一个被控制显隐的div</div>
</div>
<div>
<!-- 功能二模板 -->
<button @click="changeRed">红色</button>
<button @click="changeYellow">蓝色</button>
<div class="box" :style="`color:${fontColor}`">一个被控制字体颜色的的div</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
showDiv: true, // 功能一数据
fontColor: '' // 功能二数据
}
},
methods: {
// 功能一方法
show() {
this.showDiv = true
},
hide() {
this.showDiv = false
},
// 功能二方法
changeRed() {
this.fontColor = 'red'
},
changeYellow() {
this.fontColor = 'blue'
}
}
}
</script>
Vue3实现
<template>
<div>
<!-- 功能一模板 -->
<button @click="show">显示</button>
<button @click="hide">隐藏</button>
<div class="box" v-if="showDivFlag">一个被控制显隐的div</div>
</div>
<div>
<!-- 功能二模板 -->
<button @click="changeRed">红色</button>
<button @click="changeBlue">蓝色</button>
<div class="box" :style="`color:${fontColor}`">一个被控制字体颜色的的div</div>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
name: 'App',
setup() {
// 功能一
const showDiv = ref(true)
function show() {
showDiv.value = true
}
function hide() {
showDiv.value = false
}
// 功能二
const fontColor = ref('')
function changeRed() {
fontColor.value = 'red'
}
function changeYellow() {
fontColor.value = 'blue'
}
return { showDiv, show, hide, fontColor, changeRed, changeYellow }
}
}
</script>
组合式API vs 选项式API
Vue2的选项式(options) API 开发的页面如左图所示,各个代码都有固定的书写位置,页面大了之后,会有来回上下找代码的困境;
Vue3的组件式(composition) API 开发的页面如右图所示,特定功能的所有代码放到一起维护,不论页面多大,都可以快速定位到某个功能的所有相关代码,方便阅读、维护;如果功能复杂,还可以进行逻辑拆分处理;
组合式API优化
通过定义功能函数,把两个功能相关的代码各自抽离到一个独立的小函数中,然后通过在setup函数中再把两个小功能函数组合起来,这样一来,既可以把setup函数变得清爽,又可以方便维护快速定位功能位置;
<script>
import { ref } from 'vue'
function useShow() {
const showDivFlag = ref(true)
function show() {
showDivFlag.value = true
}
function hide() {
showDivFlag.value = false
}
return { showDivFlag, show, hide }
}
function useColor() {
const fontColor = ref('')
function changeRed() {
fontColor.value = 'red'
}
function changeBlue() {
fontColor.value = 'blue'
}
return { fontColor, changeRed, changeBlue }
}
export default {
name: 'App',
setup() {
// 功能一
const { showDivFlag, show, hide } = useShow()
// 功能二
const { fontColor, changeRed, changeBlue } = useColor()
return { showDivFlag, show, hide, fontColor, changeRed, changeBlue }
}
}
</script>
setup
组件选项
setup
选项在组件被创建之前执行,一旦 props
被解析完成,它将被作为组合式 API 的入口;
在 setup
中应该避免使用 this
,因为setup
的调用发生在 data
property、computed
property 或 methods
被解析之前,所以它们无法在 setup
中被获取。
setup
选项接收 props
和 context
参数,我们将在之后进行讨论。 setup
中返回的所有内容都暴露给组件的其余部分 (例如:计算属性、方法、生命周期钩子等) 以及组件的模板。
带 ref
的响应式变量
在 Vue 3.0 中,我们可以通过一个新的 ref
函数使任何响应式变量在任何地方起作用,如下所示:
import { ref } from 'vue'
const counter = ref(0)
ref
接收参数并将其包裹在一个带有 value
property 的对象中返回,然后可以使用该 property 访问或更改响应式变量的值:
import { ref } from 'vue'
const counter = ref(0)
console.log(counter) // { value: 0 }
console.log(counter.value) // 0
counter.value++
console.log(counter.value) // 1
将值封装在一个对象中,看似没有必要,但为了保持 JavaScript 中不同数据类型的行为统一,这是必须的。这是因为在 JavaScript 中,Number
或 String
等基本类型是通过值而非引用传递的:
在任何值周围都有一个封装对象,这样我们就可以在整个应用中安全地传递它,而不必担心在某个地方失去它的响应性。
提示
换句话说,ref
为我们的值创建了一个响应式引用。在整个组合式 API 中会经常使用引用的概念。
再例:const repositories = ref([])