Vue2大家熟悉的mixins大数用来把组件逻辑提取到可以复用的单元里面,然而mixins的三个主要短板:
1、不清晰的数据来源(组件出现多个mixin时)
2、命名空间冲突(合作开发导致)
3、隐式的跨mixin交流 (多个 mixin 需要依赖共享的属性名来进行相互作用,这使得它们隐性地耦合在一起)
所以Vue3其一组合式函数**
-
组合式函数: 利用Vue的组合式API来封装和复用有状态逻辑的函数,直接理解为组合式函数的形式提取到外部文件中, 更酷的是: 可嵌套多个组合式函数。一个组合式函数可以调用一个或多个其他的组合式函数,直接上示例1:
//collection.js 点击收藏 import { ref, onMounted, onUnmounted } from 'vue' // 按照惯例,组合式函数名以“use”开头 export function useCollection() { const isCollection = ref<boolean>(false) // 组合式函数可以随时更改其状态 function changeCollection(){ isCollection.value = !isCollection.value // 接口 fetch(...).then() } return { isCollection, changeCollection } }
在组件中使用的方式:
<script setup>
import { useCollection } from '@/common/collection.js'
const { isCollection, changeCollection } = useCollection()
</script>
<template>
<span :class="['iconfont', isCollection ? 'icon-shoucang' : 'icon-qudiao']" @click="changeCollection"></span>
</template>
示例2: 输入框交互后台动态数据查询
search.js isRef: 方法判断是否响应式 unref:方法解包可能为ref的值 watchEffect:方法启动一个响应式的effect
import { ref, isRef, unrec, watchEffect } from 'vue'
export function useSearch(url, text){
const data = ref(null)
const error = ref(null)
const textValue = unref(text)
try{
await timeout()
const res = await doSearchFetch(url, textValue)
data.value = await res.json()
} catch (e) {
error.value = e
}
async function doSearchFetch(){
data.value = null
error.value = null
fetch(url, unref(textValue))
.then((res) => data.value = res)
.catch((err) => error.value = err)
}
// 如果value值是一个ref, 则开启响应式的请求
if(isRef(text)){
watchEffect(doSearchFetch)
} esle{
// 否则只请求一次,避免监听器的额外开销
doSearchFetch()
}
return {
data,
error
}
}
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.3) {
resolve()
} else {
reject(new Error('Error'))
}
}, 300)
})
}
组件使用:
<script setup>
import { useSearch } from '@/common/search.js'
const searchValue = ref()
const { data, error } = useSearch('/api/search', searchValue)
</script>
<template>
<input :value="searchValue" plahoader="请输入查询内容" />
<ul>
<li v-for="item in data" :key="item.id">{{ item.lable }}</li>
</ul>
</template>