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

Vue3的自定义的hook

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

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

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

手写自定义hook 案例一

1.新建 hooks/iondex.ts 文件 
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.在文件中使用
<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**   主要侦听元素是否在视口内

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 文件中配置

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 文件

{
  "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 命令后 打包
在这里插入图片描述
6. 在 index.d.ts 编写声明文件

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
{
  "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 的实例
    
<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. 在文件中使用 示例如下
<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>

  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue3,自定义hook其实就是一个普通的函数,该函数可以使用Vue3的响应式API和生命周期钩子。自定义hook的目的是将一些逻辑抽象出来,使组件逻辑更加清晰。 自定义hook的命名一般以"use"开头,例如"useFetch","useLocalStorage"等。下面是一个示例: ```js import { ref, onMounted } from 'vue' export function useFetch(url) { const data = ref(null) const isLoading = ref(false) const error = ref(null) onMounted(async () => { isLoading.value = true try { const response = await fetch(url) data.value = await response.json() } catch (err) { error.value = err.message } finally { isLoading.value = false } }) return { data, isLoading, error } } ``` 在上面的代码,我们定义了一个名为"useFetch"的自定义hook,它接受一个URL作为参数,并返回一个包含数据、加载状态和错误的响应式对象。在这个hook,我们使用了Vue3的ref函数来创建响应式数据,使用onMounted钩子来在组件挂载时执行异步请求。最后,我们将数据、加载状态和错误返回给调用该hook的组件。 可以在组件使用这个自定义hook,如下所示: ```js <template> <div v-if="isLoading">Loading...</div> <div v-else-if="error">{{ error }}</div> <div v-else>{{ data }}</div> </template> <script> import { useFetch } from './useFetch' export default { setup() { const { data, isLoading, error } = useFetch('https://jsonplaceholder.typicode.com/todos/1') return { data, isLoading, error } } } </script> ``` 在上面的代码,我们从我们的自定义hook导入了"data"、"isLoading"和"error",然后将它们返回给组件。组件可以直接使用这些响应式数据,而不必担心如何处理异步请求的细节。这使得组件的代码更加简洁和易于维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值