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>
相关推荐
gongzemin5 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox18 分钟前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
-代号952722 分钟前
【JavaScript】十四、轮播图
javascript·css·css3
麦麦大数据41 分钟前
neo4j+django+deepseek知识图谱学习系统对接前后端分离前端vue
vue.js·django·知识图谱·neo4j·deepseek·在线学习系统
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼1 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX187301 小时前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下1 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞2 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox