vue3中Hook使用以及Hook結(jié)合自定義指令
Vue3的自定義的hook
hook是鉤子的意思,看到“鉤子”是不是就想到了鉤子函數(shù)?事實上,hooks 還真是函數(shù)的一種寫法。
vue3 借鑒 reacthooks 開發(fā)出了 Composition API ,所以也就意味著 Composition API 也能進行自定義封裝 hooks。
vue3 中的 hooks就是函數(shù)的一種寫法,就是將文件的一些單獨功能的js代碼進行抽離出來,放到單獨的js文件中,或者說是一些可以復(fù)用的公共方法/功能。
其實hooks 和 vue2 中的 mixin 有點類似,但是相對 mixins 而言, hooks 更清楚復(fù)用功能代碼的來源, 更清晰易懂。
Vue3 hook庫:hook 官網(wǎng)
手寫自定義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.展示效果 在控制臺顯示 然后復(fù)制 base64碼 到瀏覽器 可顯示圖片

手寫自定義hook 案例二

需求:
實現(xiàn)一個函數(shù)同事支持hook 和自定義指令 去監(jiān)聽dom寬高的變化 5w3h 八何分析法
- 1.如何監(jiān)聽dom寬高變化
- 2.如何用vite打包庫
- 3.如何發(fā)布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主要偵聽元素是否在視口內(nèi)
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 useResize3.打包 成為一個庫
在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 構(gòu)建模式下為這些外部化的依賴提供一個全局變量
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 useResize7.準(zhǔn)備就緒 發(fā)布npm 需要配置 package.json
- 當(dāng)使用import 、export的時候它會去找對應(yīng)的module
- 當(dāng)使用require的時候 它會去找對應(yīng)的main
- 然后配置files是往 npm 上發(fā)布的目錄
- 修改版本因為是第一次發(fā)布 改成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"
}
}
8.上傳npm
如果沒有npm 賬號
npm adduser
有賬號的話 npm login
上傳插件 npm publish

9.上傳成功后
可以去npm 官網(wǎng) 搜索package.json 定義的 name 名稱進行搜索
10.使用
在項目中安裝庫
pnpm i v-resize-smy
在文件中引入
一下代碼自定義hook 的實例
<template>
<div id="resize">
<a rel="external nofollow" rel="external nofollow" 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>
11.自定義指令+hook 綜合使用案例
在main.ts 文件中注冊
import useResize from “v-resize-smy” app.use(useResize)
在文件中使用 示例如下
<template>
<div v-resize="resizeWd" id="resize">
<a rel="external nofollow" rel="external nofollow" 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>
hooks 優(yōu)點
- 1.hooks 作為獨立邏輯的組件封裝,其內(nèi)部的屬性、函數(shù)等和外部組件具有響應(yīng)式依附的作用。
- 2.自定義 hook 的作用類似于 vue2 中的 mixin 技術(shù),使用方便,易于上手。
- 3.使用 Vue3 的組合 API 封裝的可復(fù)用,高內(nèi)聚低耦合。
hooks和utils區(qū)別
相同點:
- 通過 hooks 和 utils 函數(shù)封裝, 可以實現(xiàn)組件間共享和復(fù)用,提高代碼的可重用性和可維護性。
異同點:
- 表現(xiàn)形式不同:hooks 是在 utils 的基礎(chǔ)上再包一層組件級別的東西(鉤子函數(shù)等);utils一般用于封裝相應(yīng)的邏輯函數(shù),沒有組件的東西;
- 數(shù)據(jù)是否具有響應(yīng)式:hooks 中如果涉及到 ref,reactive,computed 這些 api 的數(shù)據(jù),是具有響應(yīng)式的;而utils 只是單純提取公共方法就不具備響應(yīng)式;
- 作用范圍不同:hooks 封裝,可以將組件的狀態(tài)和生命周期方法提取出來,并在多個組件之間共享和重用;utils通常是指一些輔助函數(shù)或工具方法,用于實現(xiàn)一些常見的操作或提供特定功能。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用VUE實現(xiàn)一鍵復(fù)制內(nèi)容功能
這篇文章主要介紹了使用VUE實現(xiàn)一鍵復(fù)制內(nèi)容功能,功能就是當(dāng)我們點擊復(fù)制按鈕時,會提示“復(fù)制成功”,這樣復(fù)制的內(nèi)容就可以在其他地方使用了,感興趣的朋友可以學(xué)習(xí)一下2023-04-04
vue.js與element-ui實現(xiàn)菜單樹形結(jié)構(gòu)的解決方法
本文通過實例給大家介紹了vue.js與element-ui實現(xiàn)菜單樹形結(jié)構(gòu),非常不錯,具有參考借鑒價值,需要的朋友可以參考下2018-04-04
從Echarts報錯中學(xué)習(xí)Vue3?ref和shallowRef區(qū)別及其組件二次封裝demo
這篇文章主要介紹了從Echarts報錯中學(xué)習(xí)Vue3?ref和shallowRef區(qū)別及其組件二次封裝demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11
Vue.js設(shè)計與實現(xiàn)無限遞歸學(xué)習(xí)總結(jié)
這篇文章主要為大家介紹了Vue.js設(shè)計與實現(xiàn)無限遞歸學(xué)習(xí)總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05
Vue-router路由判斷頁面未登錄跳轉(zhuǎn)到登錄頁面的實例
下面小編就為大家?guī)硪黄猇ue-router路由判斷頁面未登錄跳轉(zhuǎn)到登錄頁面的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10

