红枫心声社区

 找回密码
 立即注册

手机动态码快速登录

手机号快速注册登录

搜索
热搜: 活动
查看: 300|回复: 0

Vue3.0 完全教程#4

[复制链接]

33

主题

33

帖子

219

积分

正式会员

Rank: 3Rank: 3

积分
219

活跃会员

发表于 2022-4-30 10:23:19 | 显示全部楼层 |阅读模式
本帖最后由 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而封装。要看具备场景:是否有复用的价值?是否有利于逻辑的分离?是否有助提升代码的可阅读性和可维护性?


您需要登录后才可以回帖 登录 | 立即注册 手机动态码快速登录

本版积分规则

快速回复 返回顶部 返回列表