本帖最后由 lovelilt 于 2022-4-30 10:37 编辑
四、自定义 Hooks 封装1、为什么要封装 Hooks ?
我们都知道,在Vue2中,在同一个.vue组件中,当 data、methods、computed、watch 的体量较大时,代码将变得臃肿。为了解决代码臃肿问题,我们除了拆分组件外,别无它法。
在Vue3中,同样存在这样的问题:当我们的组件开始变得更大时,逻辑关注点将越来越多,这会导致组件难以阅读和理解。但是,在Vue3中,我们除了可以拆分组件,还可以使用 Hooks封装来解决这一问题。
所谓 Hooks封装,就是把不同的逻辑关注点抽离出来,以达到业务逻辑的独立性。这一思路,也是Vue3 对比Vue2的最大亮点之一。
2、如何封装 Hooks 呢?
在 setup 组合的开发模式下,把具体某个业务功能所用到的 ref、reactive、watch、computed、watchEffect 等,提取到一个以 use* 开头的自定义函数中去。
封装成 use* 开头的Hooks函数,不仅可以享受到封装带来的便利性,还有利于代码逻辑的复用。Hooks函数的另一个特点是,被复用时可以保持作用域的独立性,即,同一个Hooks函数被多次复用,彼此是不干扰的。
3、在哪些情况下需要封装 Hooks呢?
我总结了两种场景:一种是功能类Hooks,即为了逻辑复用的封装;另一种是业务类Hooks,即为了逻辑解耦的封装。下面我给两组代码,说明这两种使用场景。
4、示例:功能类 Hooks封装
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { useStore } from 'vuex'
// 返回路由常用信息
export function useLocation() {
const route = useRoute()
const pathname = route.fullPath
return { pathname }
}
// 用于方便地访问Vuex数据
export function useSelector(fn) {
const store = useStore()
// Vuex数据要用computed包裹,处理响应式问题
return computed(()=>fn(store.state))
}
// 用于派发actions的
export function useDispatch() {
const store = useStore() return store.dispatch
}
5、示例:业务类 Hooks封装 import { ref, computed, watch, watchEffect } from 'vue'
import { useDispatch, useSelector } from '@/hooks'
// 业务逻辑封装
export function useCnode() {
let tab = ref('') // tab.value
let page = ref(1) // page.value
const dispatch = useDispatch()
// 使用 store数据
const cates = useSelector(state=>state.cnode.cates)
const list = useSelector(state=>state.cnode.list)
// 用于处理list列表数据
const newList = computed(()=>{
const result = []
list.value.forEach(ele1=>{
const cate = cates.value.find(ele2=>ele2.tab===ele1.tab)
ele1['label'] = ele1.top ? '置顶' : ( ele1.good ? '精华' : (cate?.label||'问答'))
ele1['first'] = tab.value===''
result.push(ele1)
})
return result
})
// 相当于react中useEffect(fn, [])
// watchEffect,它可以自动收集依赖项
watchEffect(()=>{
dispatch('cnode/getList',{tab:tab.value,limit:5,page:page.value})
})
// 当品类发生变化时,页码重置为第一页
watch(tab, ()=>page.value=1)
return [tab, page, newList]
}
最后想说的是,不能为了封装Hooks而封装。要看具备场景:是否有复用的价值?是否有利于逻辑的分离?是否有助提升代码的可阅读性和可维护性?
|