vue3中Hook使用以及Hook結(jié)合自定義指令
Vue3的自定義的hook
hook是鉤子的意思,看到“鉤子”是不是就想到了鉤子函數(shù)?事實(shí)上,hooks 還真是函數(shù)的一種寫(xiě)法。
vue3 借鑒 reacthooks 開(kāi)發(fā)出了 Composition API ,所以也就意味著 Composition API 也能進(jìn)行自定義封裝 hooks。
vue3 中的 hooks就是函數(shù)的一種寫(xiě)法,就是將文件的一些單獨(dú)功能的js代碼進(jìn)行抽離出來(lái),放到單獨(dú)的js文件中,或者說(shuō)是一些可以復(fù)用的公共方法/功能。
其實(shí)hooks 和 vue2 中的 mixin 有點(diǎn)類(lèi)似,但是相對(duì) mixins 而言, hooks 更清楚復(fù)用功能代碼的來(lái)源, 更清晰易懂。
Vue3 hook庫(kù):hook 官網(wǎng)
手寫(xiě)自定義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.展示效果 在控制臺(tái)顯示 然后復(fù)制 base64碼 到瀏覽器 可顯示圖片
手寫(xiě)自定義hook 案例二
需求:
實(shí)現(xiàn)一個(gè)函數(shù)同事支持hook 和自定義指令 去監(jiān)聽(tīng)dom寬高的變化 5w3h 八何分析法
- 1.如何監(jiān)聽(tīng)dom寬高變化
- 2.如何用vite打包庫(kù)
- 3.如何發(fā)布npm
1.新建工程 V-RESIZE-XM
新建src/index.ts文件
- - 輸入 pnpm init 終端命令 生成 package.json 配置文件
- - 輸入 tsc --init 終端名稱(chēng) 生成 tsconfig.json 配置文件
- - 新建 vite.config.ts 文件
- - 新建 index.d.ts 文件
- - 安裝 兩個(gè)庫(kù) pnpm i vue -D pnpm i vite -D
2.進(jìn)入 src/index.ts文件中完成hook
ResizeObserver
主要偵聽(tīng)元素寬高的變化MutationObserver
主要偵聽(tīng)子集的變化 還有屬性的變化 以及 增刪改查interSectionObserver
主要偵聽(tīng)元素是否在視口內(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 useResize
3.打包 成為一個(gè)庫(kù)
在vite.config.ts 文件中配置
import { defineConfig } from 'vite' // umd 支持amd cmd cjs 全局變量模式 export default defineConfig({ build: { lib: { entry: 'src/index.ts', name: 'userResize', }, rollupOptions: { // 確保外部化處理那些你不想打包進(jìn)庫(kù)的依賴(lài) external: ['vue'], output: { // 在 UMD 構(gòu)建模式下為這些外部化的依賴(lài)提供一個(gè)全局變量 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 編寫(xiě)聲明文件
declare const useResize: { (el: HTMLElement, callback: Function): void; install: (app: App) => void }; export default useResize
7.準(zhǔn)備就緒 發(fā)布npm 需要配置 package.json
- 當(dāng)使用import 、export的時(shí)候它會(huì)去找對(duì)應(yīng)的module
- 當(dāng)使用require的時(shí)候 它會(huì)去找對(duì)應(yīng)的main
- 然后配置files是往 npm 上發(fā)布的目錄
- 修改版本因?yàn)槭堑谝淮伟l(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
如果沒(méi)有npm 賬號(hào)
npm adduser
有賬號(hào)的話(huà) npm login
上傳插件 npm publish
9.上傳成功后
可以去npm 官網(wǎng) 搜索package.json 定義的 name 名稱(chēng)進(jìn)行搜索
10.使用
在項(xiàng)目中安裝庫(kù)
pnpm i v-resize-smy
在文件中引入
一下代碼自定義hook 的實(shí)例
<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 文件中注冊(cè)
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)點(diǎn)
- 1.hooks 作為獨(dú)立邏輯的組件封裝,其內(nèi)部的屬性、函數(shù)等和外部組件具有響應(yīng)式依附的作用。
- 2.自定義 hook 的作用類(lèi)似于 vue2 中的 mixin 技術(shù),使用方便,易于上手。
- 3.使用 Vue3 的組合 API 封裝的可復(fù)用,高內(nèi)聚低耦合。
hooks和utils區(qū)別
相同點(diǎn):
- 通過(guò) hooks 和 utils 函數(shù)封裝, 可以實(shí)現(xiàn)組件間共享和復(fù)用,提高代碼的可重用性和可維護(hù)性。
異同點(diǎn):
- 表現(xiàn)形式不同:hooks 是在 utils 的基礎(chǔ)上再包一層組件級(jí)別的東西(鉤子函數(shù)等);utils一般用于封裝相應(yīng)的邏輯函數(shù),沒(méi)有組件的東西;
- 數(shù)據(jù)是否具有響應(yīng)式:hooks 中如果涉及到 ref,reactive,computed 這些 api 的數(shù)據(jù),是具有響應(yīng)式的;而utils 只是單純提取公共方法就不具備響應(yīng)式;
- 作用范圍不同:hooks 封裝,可以將組件的狀態(tài)和生命周期方法提取出來(lái),并在多個(gè)組件之間共享和重用;utils通常是指一些輔助函數(shù)或工具方法,用于實(shí)現(xiàn)一些常見(jiàn)的操作或提供特定功能。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue填坑之webpack run build 靜態(tài)資源找不到的解決方法
今天小編就為大家分享一篇vue填坑之webpack run build 靜態(tài)資源找不到的解決方法。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Vuex實(shí)現(xiàn)計(jì)數(shù)器以及列表展示效果
這篇文章主要為大家詳細(xì)介紹了Vuex實(shí)現(xiàn)計(jì)數(shù)器以及列表展示效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03Vue的Eslint配置文件eslintrc.js說(shuō)明與規(guī)則介紹
最近在跟著視頻敲項(xiàng)目時(shí),代碼提示出現(xiàn)很多奇奇怪怪的錯(cuò)誤提示,百度了一下是eslintrc.js文件沒(méi)有配置相關(guān)命令,ESlint的語(yǔ)法檢測(cè)真的令人抓狂,現(xiàn)在總結(jié)一下這些命令的解釋2020-02-02vue項(xiàng)目使用axios發(fā)送請(qǐng)求讓ajax請(qǐng)求頭部攜帶cookie的方法
今天小編就為大家分享一篇vue項(xiàng)目使用axios發(fā)送請(qǐng)求讓ajax請(qǐng)求頭部攜帶cookie的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09vue數(shù)據(jù)push后不能響應(yīng)式更新的問(wèn)題
這篇文章主要介紹了vue數(shù)據(jù)push后不能響應(yīng)式更新的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03vue打包生成的文件的js文件過(guò)大的優(yōu)化方式
這篇文章主要介紹了vue打包生成的文件的js文件過(guò)大的優(yōu)化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04vue create、vue webpack init創(chuàng)建vue項(xiàng)目產(chǎn)生的項(xiàng)目文件的區(qū)別
這篇文章主要介紹了vue create、vue webpack init創(chuàng)建vue項(xiàng)目產(chǎn)生的項(xiàng)目文件的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11