如何封装一个hook | 青训营笔记

85 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 15 天

前言

最近在做项目的时候用了好多vueuse的函数,感觉他们实在是太强大了,这里试着了解一下一个hook是如何编写的

为什么要写hook

一句话,为了更好的封装。最近看了这篇文章,感触挺深

juejin.cn/post/706695…

思路

  • 因为主要用vue技术栈,这些首先创建一个vue工程,注意版本要选择成vue3,因为我们要用到组合式api
  • 然后新建一个ts文件,这里为useBase64.ts,目标封装一个根据img元素的id,来转换成一个base64的url的hook
  • 我们知道vue是在onMounted阶段才会生成dom,所以首先会引入onMounted
  • 接着确定入参为dom标签,然后返回类型为一个promise,里面是一个string类型的字符串
  • 然后用img的onload方法resolve这个promise,意味着图片一加载就返回一个baseUrl
  • 这里用到了一个base64的函数
  • 这里主要创建了一个canvas元素
  • 然后将图片的宽高都赋值给了这个canvas元素
  • 然后创建一个2d画布,将图片源、绘制的坐标(这里是0,0)和宽高都添加上
  • 最后转成URL返回
import { onMounted } from 'vue'interface Options {
  el: string
}
​
export default function (options: Options): Promise<{baseUrl: string}> {
  return new Promise((resolve, reject) => {
    onMounted(() => {
      let img: HTMLImageElement = document.querySelector(options.el) as HTMLImageElement
      img.onload = () => {
        resolve({baseUrl: base64(img)})
      }
    })
    const base64 = (img: HTMLImageElement) => {
      const canvas = document.createElement('canvas')
      canvas.width = img.width
      canvas.height = img.height
      const ctx = canvas.getContext('2d')
      // 坐标 0 0
      ctx?.drawImage(img, 0, 0, img.width, img.height)
      return canvas.toDataURL('image/png')
    }
  })
}
​

测试代码

  • 这里先定义了一个img标签,然后src为vite工程自带的vite logo
  • 然后引入了自己写的hook,然后传了img的ID
  • 然后利用then,输出hook返回的promise
<script setup lang="ts">
import useBase64 from './hooks/useBase64'
useBase64({ el: '#img' }).then(res =>
  console.log(res)
)
</script><template>
  <div>
    <img id="img" src="/vite.svg" class="logo" alt="Vite logo" />
  </div>
</template>

结果

iShot_2023-02-14_23.44.02.jpg

我们可以看到,控制台成功输出了一个baseUrl,我们复制出来然后在浏览器上粘贴,成功展示出来,说明我们的图片是没有问题的。

image-20230214234949632.png

总结

本次练习通过网上的教程自己学着封装了一个hook,vueuse上还有很多大佬已经封装好的hook,到时候参考一下,制作一个符合业务的hook。总体思路是一致的 都遵照着 "定义状态数据","操作状态数据","隐藏细节" 作为核心思路,做到繁琐封装,使用简单。听说Vueuse和element-plus源码很漂亮,抓紧时间学起来吧!