写点什么

Vue3 必会技巧 - 自定义 Hooks

作者:yyds2026
  • 2022-11-07
    浙江
  • 本文字数:3426 字

    阅读完需:约 11 分钟

Vue3 自定义 Hooks 定义:

个人理解:一些可复用的方法像钩子一样挂着,可以随时被引入和调用以实现高内聚低耦合的目标,应该都能算是 hook;

为什么 Vue3 要用自定义 Hook?:

结论:就是为了让Compoosition Api更好用更丰满,让写 Vue3 更畅快!像写诗一样写代码!其实这个问题更深意义是为什么 Vue3 比 Vue2 更好!无外呼性能大幅度提升,其实编码体验也是 Vue3 的优点**Composition Api的引入(解决 Option Api 在代码量大的情况下的强耦合)** 让开发者有更好的开发体验。


个人碎碎念:但是这些所谓的提高开发体验都是需要开发者不断学习养成编码好习惯,同样是 Vue3 写 Compoosition Api 有的人就能写得和诗一样,有的人却能写得像💩一样(衷心希望每个开发者都有一颗对技术热衷的心,不要为了开发而开发,前人写翔让后人尝!抱歉最近因为维护老项目太多感慨)

写 Vue3 请摆脱 Vue2 无脑 this 的思想:

写 Vue2 中很多同学养成了 Option Api无脑 this 的习惯,来到Vue3Composition Api还是习惯性想用 this,更有人为了写 this 不惜引入getCurrentInstance!这大可不必!


Composition Api的优点之一就是摆脱无脑 this 导致的强耦合,功能之间互相 this,变量和方法在各个方法混杂,无处不在的 this 是强耦合的,虽然方便,但是碎片化的 option api 后期维护是麻烦的。


我相信写Vue2的同学,一定深有感触,一个组件下定义大量变和大量方法,方法嵌套方法,方法之间互相共享变量,维护这样的代码,看似容易理解的Option Api写法,我们需要在methos、data、template之间来回切,Option Api这种写法,代码量和功能小巧时是十分简单明了的,但是代码量一多,功能一复杂,我相信 review 代码的时候头都痛。


相对的Composition Api在功能复杂、代码量巨大的组件下,我们配合自定义 Hooks,将代码通过功能分块写响应变量和方法在一起定义和调用,这样后期我们改功能 A 只需要关注功能 A 块下的代码,不会像 Vue2 在Option Api需要同时关注 methos 和 data。。。。。

几张动图再来复习一遍 Composition Api 好!

谢谢 大帅老猿 老师做的动图,Composition Api VS Option Api 的优缺点十分明了展示在了动画上!

Option Api代码量少还好,代码量多容易导致高耦合!

说明:上面是Vue2 Option Api的写法,一个组件下含有data 、methos、computed、watch,同一个功能需要分开写在这些函数上,如果代码量少,那看起来似乎十分明了清晰。一旦代码量大功能复杂,各个功能分开写,维护的时候data 、methos、computed、watch都需要来回切,反而显得过于分散,又高度耦合

Composition Api解耦Vue2 Option Api实现低耦合高内聚

说明:如果是Composition Api在功能复杂、代码量巨大的组件下,我们配合自定义 Hook,将代码按功能分块写,变量和方法在一起定义和调用,比如 A 功能下集成了响应式变量和方法,我们后期维护只需要改动 A 功能模块下的代码,不会像 Vue2 在Option Api需要同时关注逻辑分散的 methos 和 data。


所以自定义 Hook 的写 Vue3 必须掌握的!它无不体现 Vue3 Composition Api 低耦合高内聚的思想! 笔者在看了官方文档和开源的 admin 模板都是大量使用自定义 Hooks 的!

大胆定义一下 Vue3 的自定义 Hook:

虽然官方没有明确指明或定义什么是自定义 Hooks,但是却无处不在用;

以函数形式抽离一些可复用的方法像钩子一样挂着,随时可以引入和调用,实现高内聚低耦合的目标;


  1. 将可复用功能抽离为外部 JS 文件

  2. 函数名/文件名以 use 开头,形如:useXX

  3. 引用时将响应式变量或者方法显式解构暴露出来如:const {nameRef,Fn} = useXX()

  4. (在 setup 函数解构出自定义 hooks 的变量和方法)

实例:

简单的加减法计算,将加法和减法抽离为 2 个自定义 Hooks,并且相互传递响应式数据


  • 加法功能-Hook


import { ref, watch } from 'vue';const useAdd= ({ num1, num2 })  =>{    const addNum = ref(0)    watch([num1, num2], ([num1, num2]) => {        addFn(num1, num2)    })    const addFn = (num1, num2) => {        addNum.value = num1 + num2    }    return {        addNum,        addFn    }}export default useAdd
复制代码


  • 减法功能-Hook


//减法功能-Hookimport { ref, watch } from 'vue';export function useSub  ({ num1, num2 }){    const subNum = ref(0)    watch([num1, num2], ([num1, num2]) => {        subFn(num1, num2)    })    const subFn = (num1, num2) => {        subNum.value = num1 - num2    }    return {        subNum,        subFn    }}
复制代码


  • 加减法计算组件


<template>    <div>        num1:<input v-model.number="num1" style="width:100px" />        <br />        num2:<input v-model.number="num2" style="width:100px" />    </div>    <span>加法等于:{{ addNum }}</span>    <br />    <span>减法等于:{{ subNum }}</span></template><script setup>import { ref } from 'vue'import useAdd from './useAdd.js'     //引入自动hook import { useSub } from './useSub.js' //引入自动hook const num1 = ref(2)const num2 = ref(1)//加法功能-自定义Hook(将响应式变量或者方法形式暴露出来)const { addNum, addFn } = useAdd({ num1, num2 })addFn(num1.value, num2.value)//减法功能-自定义Hook (将响应式变量或者方法形式暴露出来)const { subNum, subFn } = useSub({ num1, num2 })subFn(num1.value, num2.value)</script>
复制代码

通过上述示例再来说说 Vue3 自定义 Hooks 和 Vue2 时代 Mixin 的关系:

参考 vue 实战视频讲解:进入学习


Mixin不足在 Vue 2 中,mixin 是将部分组件逻辑抽象成可重用块的主要工具。但是,他们有几个问题:1、Mixin 很容易发生冲突:因为每个 mixin 的 property 都被合并到同一个组件中,所以为了避免 property 名冲突,你仍然需要了解其他每个特性。2、可重用性是有限的:我们不能向 mixin 传递任何参数来改变它的逻辑,这降低了它们在抽象逻辑方面的灵活性。
复制代码


上面这段是 Vue3 官方文档的内容,可以概括和补充为:

1、Mixin 难以追溯的方法与属性!Vue3 自定义 Hooks 却可以

Vue3 自定义 Hooks, 引用时将响应式变量或者方法显式暴露出来如:

const {nameRef,Fn} = useXX()


  • Mixins

  • Mixin 不明的混淆,我们根本无法获知属性来自于哪个 Mixin 文件,给后期维护带来困难

  • Vue3 自定义 Hooks

  • 我们很容易看出每个 Hooks 显式暴露出来的响应式变量和方法

2、无法向 Mixin 传递参数来改变逻辑,但是 Vue3 自定义 Hooks 却可以:

Vue3 自定义 Hooks 可以灵活传递任何参数来改变它的逻辑,参数不限于其他 hook 的暴露出来的变量,


  • Mixins


export default {  mixins: [ addMixin, subMixin], //组件内混入加法和减法Mixin  mounted(){      this.add(num1,num2) //调用addMixin内部的add方法      this.sub(num1,num2) //调用subMixin内部的sub方法  }  }
复制代码


可以通过调用 Mixin 内部方法来传递参数,却无法直接给 Mixin 传递参数,因为 Mixin 不是函数形式暴露的,不发传参


  • Vue3 自定义 Hook

  • 在上面实例基础上添加个算平均的 Hook

  • 组件内

  • Vue3 自定义 Hooks 可以灵活传递任何参数来改变它的逻辑,参数不限于其他 hook 的暴露出来的变量,这提高了 Vue3 在抽象逻辑方面的灵活性。

3、Mixin 同名变量会被覆盖,Vue3 自定义 Hook 可以在引入的时候对同名变量重命名

  • Mixins

  • 如果this.add(num1,num2)this.sub(num1,num2) 计算的结果返回的同名变量 totalNum,由于 JS 单线程,后面引入的会覆盖前面的,totalNum 最终是减法 sub 的值

  • Vue3 自定义 Hooks

  • 在 Vue3 自定义 Hooks 中,虽然加法和减法 Hooks 都返回了 totalNum,但是利用 ES6 对象解构很轻松给变量重命名

总结:

Vue2 时代Option Api ,data、methos、watch.....分开写,这种是碎片化的分散的,代码一多就容易高耦合,维护时来回切换代码是繁琐的!


Vue3 时代Composition Api,通过利用各种 Hooks 和自定义 Hooks 将碎片化的响应式变量和方法按功能分块写,实现高内聚低耦合


形象的讲法:Vue3 自定义 Hooks 是组件下的函数作用域的,而 Vue2 时代的 Mixins 是组件下的全局作用域。全局作用域有时候是不可控的,就像 var 和 let 这些变量声明关键字一样,const 和 let 是 var 的修正。Composition Api 正是对 Vue2 时代 Option Api 高耦合和随处可见 this 的黑盒的修正,Vue3 自定义 Hooks 是一种进步。


把 Mixin 和自定义 Hook 进行比较,一个是 Option Api 的体现,一个是 Composition Api 的体现。如果能理解高内聚低耦合的思想,那么就能理解为什么 Vue3 是使用 Composition Api,并通过各种自定义 Hooks 使代码更强壮。像写诗一样写代码。而不是写屎。


用户头像

yyds2026

关注

还未添加个人签名 2022-09-08 加入

还未添加个人简介

评论

发布
暂无评论
Vue3必会技巧-自定义Hooks_Vue_yyds2026_InfoQ写作社区