vue3中 Hook详解 Hook结合自定义指令

Vue3的自定义的hook

  • Vue3的hook函数 相当于vue2的mixin,不用在于hooks是函数

  • Vue3hook函数 可以帮助我们提高代码的复用性,让我们能在不能的组件中都利用hooks函数

    复制代码
     Vue3 hook库: [hook 官网](https://vueuse.org/guide/)

手写自定义hook 案例一

复制代码
1.新建 hooks/iondex.ts 文件 
javascript 复制代码
import { onMounted } from "vue"

type Options = {
    el: string
}
export default function (options: Options): Promise<{ baseUrl: string }> {
    return new Promise((resolve) => {
        onMounted(() => {
            let img: HTMLImageElement = document.querySelector(options.el) as HTMLImageElement;
            img.onload = () => {
                resolve({
                    baseUrl: base64(img)
                })
            }
        })
        const base64 = (el: HTMLImageElement) => {
            const canvas = document.createElement('canvas')
            const ctx = canvas.getContext('2d')
            canvas.width = el.width;
            canvas.height = el.height;
            ctx?.drawImage(el, 0, 0, canvas.width, canvas.height)
            return canvas.toDataURL('image/png')
        }
    })


}
复制代码
2.在文件中使用
javascript 复制代码
<template>
    <div>
        <img
            id="img"
            width="300"
            height="300"
            src="../../assets/vue.svg"
            alt=""
        />
    </div>
</template>
<script setup lang="ts">
import useBase64 from "../hooks/index"
useBase64({
    el: "img",
}).then((res) => {
    console.log(res.baseUrl)
})
</script>
<style scoped lang="scss"></style>
复制代码
3.展示效果 在控制台显示 然后复制 base64码 到浏览器 可显示图片

手写自定义hook 案例二

复制代码
需求:
	实现一个函数同事支持hook 和自定义指令 去监听dom宽高的变化
5w3h 八何分析法
	1.如何监听dom宽高变化
	2.如何用vite打包库
	3.如何发布npm
  1. 新建工程 V-RESIZE-XM

    • 新建src/index.ts文件
    • 输入 pnpm init 终端命令 生成 package.json 配置文件
    • 输入 tsc --init 终端名称 生成 tsconfig.json 配置文件
    • 新建 vite.config.ts 文件
    • 新建 index.d.ts 文件
    • 安装 两个库 pnpm i vue -D pnpm i vite -D
  2. 进入 src/index.ts文件中完成hook

    ResizeObserver 主要侦听元素宽高的变化
    MutationObserver 主要侦听子集的变化 还有属性的变化 以及 增删改查
    interSectionObserver 主要侦听元素是否在视口内

javascript 复制代码
import type { App } from 'vue'
function useResize(el: HTMLElement, callback: Function) {
    let resize = new ResizeObserver((entries) => {
        callback(entries[0].contentRect)
    })
    resize.observe(el)
}
// vue 插件
const install = (app: App) => {
    app.directive('resize', {
        mounted(el, binding) {
            useResize(el, binding.value)
        }
    })
}
useResize.install = install
export default useResize

3.打包 成为一个库
在vite.config.ts 文件中配置

javascript 复制代码
import { defineConfig } from 'vite'
// umd 支持amd cmd cjs 全局变量模式
export default defineConfig({
    build: {
        lib: {
            entry: 'src/index.ts',
            name: 'userResize',
        },
        rollupOptions: {
            // 确保外部化处理那些你不想打包进库的依赖
            external: ['vue'],
            output: {
                // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
                globals: {
                    useResize: 'useResize'
                }
            }
        }
    }
})

4.修改package.json 文件

javascript 复制代码
{
  "name": "v-resize-xm",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build":"vite build"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vite": "^5.2.11",
    "vue": "^3.4.26"
  }
}

5.npm run build 命令后 打包

  1. 在 index.d.ts 编写声明文件
javascript 复制代码
declare const useResize: {
    (el: HTMLElement, callback: Function): void;
    install: (app: App) => void
};

export default useResize
  1. 准备就绪 发布npm 需要配置 package.json
    当使用 import 、export 的时候 它会去找对应的 module
    当使用 require 的时候 它会去找对应的 main
    然后配置 files 是往 npm 上发布的目录
    修改版本 因为是第一次发布 改成 0.0.1
javascript 复制代码
{
  "name": "v-resize-xm",
  "version": "0.0.1",
  "description": "",
  "main": "dist/v-resize-xm.umd.js",
  "module": "dist/v-resize-xm.mjs",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build":"vite"
  },
  "keywords": [],
  "author": "",
  "files": [
    "dist",
    "index.d.ts"
  ],
  "license": "ISC",
  "devDependencies": {
    "vite": "^5.2.11",
    "vue": "^3.4.26"
  }
}

3.上传npm

  • 如果没有npm 账号

    1.npm adduser

  • 有账号的话 npm login

  • 上传插件 npm publish

    4.上传成功后

    可以去npm 官网 搜索package.json 定义的 name 名称进行搜索

    链接: npm官网地址

    5.使用

    复制代码
    1.在项目中安装库
    	pnpm i v-resize-smy
    2.在文件中引入
    3.一下代码自定义hook 的实例
javascript 复制代码
<template>
    <div id="resize">
        <a href="http://vitejs.dev" target="_blank">
            <img src="/vite.svg" class="logo" alt="Vite logo" />
        </a>
    </div>
</template>
<script setup lang="ts">
import useResize from "v-resize-smy"
import { onMounted } from "vue"
onMounted(() => {
    useResize(document.querySelector("#resize") as HTMLElement, (e: any) => {
        console.log(e)
    })
})
</script>
<style scoped lang="scss">
#resize {
    border: 1px solid #ccc;
    resize: both;
    overflow: hidden;
}
img {
    width: 50px;
    height: 50px;
}
</style>

6.自定义指令+hook 综合使用案例

复制代码
1. 在main.ts 文件中注册
		import useResize from "v-resize-smy"
		app.use(useResize)
2. 在文件中使用 示例如下
javascript 复制代码
<template>
    <div v-resize="resizeWd" id="resize">
        <a href="http://vitejs.dev" target="_blank">
            <img src="/vite.svg" class="logo" alt="Vite logo" />
        </a>
    </div>
</template>
<script setup lang="ts">
const resizeWd = (el: any) => {
    console.log(el)
}
</script>
<style scoped lang="scss">
#resize {
    border: 1px solid #ccc;
    resize: both;
    overflow: hidden;
}
img {
    width: 50px;
    height: 50px;
}
</style>
相关推荐
恋猫de小郭6 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅13 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606114 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了14 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅14 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅14 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅15 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment15 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅15 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊15 小时前
jwt介绍
前端