这是我参与「第五届青训营 」伴学笔记创作活动的第 15 天
前言
最近在做项目的时候用了好多vueuse的函数,感觉他们实在是太强大了,这里试着了解一下一个hook是如何编写的
为什么要写hook
一句话,为了更好的封装。最近看了这篇文章,感触挺深
思路
- 因为主要用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>
结果
我们可以看到,控制台成功输出了一个baseUrl,我们复制出来然后在浏览器上粘贴,成功展示出来,说明我们的图片是没有问题的。
总结
本次练习通过网上的教程自己学着封装了一个hook,vueuse上还有很多大佬已经封装好的hook,到时候参考一下,制作一个符合业务的hook。总体思路是一致的 都遵照着 "定义状态数据","操作状态数据","隐藏细节" 作为核心思路,做到繁琐封装,使用简单。听说Vueuse和element-plus源码很漂亮,抓紧时间学起来吧!