做网站然后推广,兰州中川国际机场电话,wordpress comment,眼科医院网站设计怎么做6一、hooks 是什么
vue3 中的 hooks 就是函数的一种写法#xff0c;就是将文件的一些单独功能的 js 代码进行抽离出来进行封装使用。
它的主要作用是 Vue3 借鉴了 React 的一种机制#xff0c;用于在函数组件中共享状态逻辑和副作用#xff0c;从而实现代码的可复用性。
注…一、hooks 是什么
vue3 中的 hooks 就是函数的一种写法就是将文件的一些单独功能的 js 代码进行抽离出来进行封装使用。
它的主要作用是 Vue3 借鉴了 React 的一种机制用于在函数组件中共享状态逻辑和副作用从而实现代码的可复用性。
注意其实 hooks 和 vue2 中的 mixin 有点类似但是相对 mixins而言 hooks 更清楚复用功能代码的来源, 更清晰易懂。
二、hooks 的优点
hooks 作为独立逻辑的组件封装其内部的属性、函数等和外部组件具有响应式依附的作用。自定义 hook 的作用类似于 vue2 中的 mixin 技术使用方便易于上手。使用 Vue3 的组合 API 封装的可复用高内聚低耦合。
三、自定义 hook 需要满足的规范
具备可复用功能才需要抽离为 hooks 独立文件函数名/文件名以 use 开头形如: useXX引用时将响应式变量或者方法显式解构暴露出来
示例如下
const{ nameRef, Fn } useXX()
四、hooks 和 utils 区别
相同点 通过 hooks 和 utils 函数封装 可以实现组件间共享和复用提高代码的可重用性和可维护性。
异同点
表现形式不同hooks 是在 utils 的基础上再包一层组件级别的东西(钩子函数等)utils 一般用于封装相应的逻辑函数没有组件的东西数据是否具有响应式hooks 中如果涉及到 refreactivecomputed 这些 api 的数据是具有响应式的而 utils 只是单纯提取公共方法就不具备响应式作用范围不同hooks 封装可以将组件的状态和生命周期方法提取出来并在多个组件之间共享和重用utils 通常是指一些辅助函数或工具方法用于实现一些常见的操作或提供特定功能。
总结 utils 是通用的工具函数而 hooks 是对 utils 的一种封装用于在组件中共享状态逻辑和副作用。 通过使用 hooks您可以简化代码并使其更具可读性和可维护性。
五、hooks 和 mixin 区别
相同点 hooks 和 mixin都是常用代码逻辑抽离手段方便进行代码复用
异同点
语法和用法不同Hooks 是在 Vue 3 的 Composition API 中引入的一种函数式编程的方式而 Mixins 是在 Vue 2 中的一种对象混入机制。Hooks 使用函数的方式定义和使用而 Mixins 则是通过对象的方式进行定义和应用。组合性和灵活性不同Hooks 允许开发者根据逻辑功能来组合代码封装为自定义 Hook 函数提高代码复用率。而 Mixins 在组件中的属性和方法会与组件本身的属性和方法进行合并可能会导致命名冲突或不可预料的行为。响应式系统不同Vue 3 的 Composition API 使用了一个新的响应式系统可以通过 reactive 和 ref 来创建响应式数据可以更精确地控制组件的更新和依赖追踪。而 Mixins 使用 Vue 2 的响应式系统对数据的追踪和更新较为简单可能存在一些性能上的问题。生命周期钩子不同在 Vue 3 的 Composition API 中可以使用 onMounted、onUpdated 等钩子函数来替代 Vue 2 中的生命周期钩子可以更灵活地管理组件的生命周期。Mixins 依然使用 Vue 2 的生命周期钩子。
mixins 的优缺点
优点组件中相同代码逻辑复用
缺点
变量来源不明确变量来源不明确隐式传入不利于阅读使代码变得难以维护。命名冲突多个 mixins 的生命周期会融合到一起运行但是同名属性、同名方法无法融合可能会导致冲突。滥用会造成维护问题mixins 和组件可能出现多对多的关系复杂度较高即一个组件可以引用多个 mixins一个 mixins 也可以被多个组件引用。
注VUE3 提出的 Composition API 旨在解决这些问题。mixins 的缺点是 Composition API 背后的主要动因之一Composition API 受到 React Hooks 的启发。
HooksMixins定义hook是通过Composition API引入的一种新特性类似于React的hook。mixin是一种对Vue组件进行扩展的方式。功能可以组织和重用逻辑。在组件中我们可以创建和重用复杂的逻辑代码使得组件的逻辑更加清晰和可维护它可以将组件的代码封装到一个可复用的模块。常用于将公用的代码片段进行抽离实现复用使得组件的逻辑更加清晰和可维护。使用使用setup方法可以组织和复用各类逻辑使用mixin属性加载公用的代码片段。组织代码效果使用Hooks我们可以让组件的逻辑函数按功能组织使得组件的逻辑结构更加清晰。使用Mixins我们可以将组件的各个生命周期的相关函数统一放在一起但这样做可能会使得组件的逻辑函数分散在各个生命周期中。冲突问题Hooks允许我们命名冲突的功能从而避免了各种命名冲突。Mixins可能会导致函数名冲突。如果两个mixin中包含相同的函数会导致后一个mixin的函数覆盖先前的函数。难以追踪的来源Hooks使用的是函数所以如果不加注释可能不太容易找到其来源。在Mixin中我们可以在每个使用了公用代码片段的地方都用注释表明这段代码的来源有助于我们更好地追踪和维护代码。Debug困难度Hooks有更好的Stack Trace可以提供更优秀的debug体验。对mixins的支持可能会出现在运行时错误的情况下无法找到那块代码出错的问题从而导致调试困难。
hooks 代码
useCount.ts 函数示例
import{ ref, onMounted, computed } fromvue;export default function useCount{constcount ref(0);constdoubleCount computed(()count.value * 2);constincrease (delta) {return count.value delta;}return{count,doubleCount,increase};}
useCount 在组件中调用
import useCount from/hooks/useCount;
const {(count, doubleCount, increase)} useCount;
const newCount increase(10); // 输出: 10 Mixins 的代码:
export default const countMixin {data() {return{count: 0};},computed: {doubleCount() {return this.count * 2;}},methods: {increase(delta){return this.count delta;}};
}
Mixins 在组件中调用
scriptsetuplangts
import count Mixin from/mixin/countMixin
export default{mixins: [countMixin],mounted() {console.log(this.doubleCount) // 输出: 0constnewCount this.setIncrease(10) // 输出: 10},methods: {setIncrease(count) {this.increase(count)},},
}
/script
这两个示例展示了使用 Hooks 和 Mixins 的代码风格和组织方式的不同。Hooks 使用函数式的方式来定义逻辑和状态而 Mixins 则是通过对象的方式进行组合和共享代码。
Vue3 自定义 Hooks 是组件下的函数作用域的而 Vue2 时代的 Mixins 是组件下的全局作用域。全局作用域有时候是不可控的就像 var 和 let 这些变量声明关键字一样const 和 let 是 var 的修正。Composition Api 正是对 Vue2 时代 Option Api 高耦合和随处可见 this 的黑盒的修正Vue3 自定义 Hooks 是一种进步。
六、hooks 函数封装示例
示例 1数据导出(useDownload)
useDownload 函数封装
import{ ElNotification } fromelement-plus
/**
* description 接收数据流生成 blob创建链接下载文件
* param {any} data 导出的文件blob数据 (必传)
* param {String} tempName 导出的文件名 (必传)
* param {Boolean} isNotify 是否有导出消息提示 (默认为 true)
* param {String} fileType 导出的文件格式 (默认为.xlsx)
* */
interface useDownloadParam {data: any;tempName: string;isNotify?: boolean;fileType?: string;
}export const useDownload async({data,tempName,isNotify true,fileType .xlsx,
}: useDownloadParam) {if(isNotify) {ElNotification({title: 温馨提示,message: 如果数据庞大会导致下载缓慢哦请您耐心等待,type: info,duration: 3000,})}
try{constblob newBlob([data])// 兼容 edge 不支持 createObjectURL 方法if(msSaveOrOpenBlob in navigator) return window.navigator.msSaveOrOpenBlob(blob, tempName fileType)const blobUrl window.URL.createObjectURL(blob)const exportFile document.createElement(a)exportFile.style.display noneexportFile.download ${tempName}${fileType}exportFile.href blobUrldocument.body.appendChild(exportFile)exportFile.click()// 去除下载对 url 的影响document.body.removeChild(exportFile)window.URL.revokeObjectURL(blobUrl)
} catch(error) {console.log(error)
}
}
useDownload 在组件中使用
scriptsetuplangts
import { useDownload } from/hooks/useDownload;const userForm reactive({})
const userListExport (){new Promise(resolve{$Request({url: $Urls.userListExport,method: post,data: userForm,responseType: blob}).then((res: any) {useDownload({data: res.data,tempName用户列表});resolve(res);});
});
};
/script
示例 2获取鼠标触发点坐标(useMousePosition)
useMousePosition 函数封装
import { ref, onMounted, onUnmounted, Ref } fromvueinterface MousePosition {x: Refnumber;y: Refnumber;
}export default function useMousePosition(): MousePosition{
constx ref(0)
consty ref(0)const updateMouse (e: MouseEvent) {
x.value e.pageX
y.value e.pageY
}onMounted((){
document.addEventListener(click, updateMouse)
})onUnmounted((){
document.removeEventListener(click, updateMouse)
})return{ x, y }
}
useMousePosition 在组件中使用
template
div
pX: {{ x }}/p
pY: {{ y }}/p
/div
/template
scriptlangts
import useMousePosition from/hooks/useMousePosition
const{ x, y } useMousePosition();
/script
示例 3封装一个发送短信验证码倒计时 hooks
useMousePosition 函数封装
templatedivinput typetext placeholder请输入验证码 v-modelcodebutton clicksendCode{{ sendBtnText }}/button/div
/templatescript langts setup
import { ref } from vue;const code ref()
const sendBtnText ref(发送验证码)
const countDownNum ref(60)
const sendCode () {//这里省略调用发送短信接口逻辑,省略禁止点击逻辑sendBtnText.value countDownNum.value sconst timer setInterval(() {countDownNum.value--sendBtnText.value countDownNum.value sif (countDownNum.value 0) {clearInterval(timer)sendBtnText.value 发送验证码countDownNum.value 60}}, 1000)
}
/script
style langcss
button {font-size: 14px;background: #23A7F2;color: #fff;
}input {height: 30px;
}
/style
这里逻辑很简单,就是点击发送按钮开启定时器出现倒计时的功能 假如我们还有其它地方用到发送短信页面,我们可以将短信发送封装成一个组件。但是如果其它页面想要使用的发送短信页面和这个组件不一样的话,我们就需要将它的逻辑抽离封装成一个 hooks 函数了,下面我们就将这个倒计时功能封装成一名为 useCountDown 的 hooks
import { Ref, ref } from vue;
export default (downNum: number
): ({ sendBtnText: Refstring, sendCode: () void }) {const sendBtnText ref(发送验证码);const countDownNum ref(downNum);//这里省略调用发送短信接口逻辑,省略禁止点击逻辑const sendCode () {sendBtnText.value countDownNum.value s;const timer setInterval(() {countDownNum.value--;sendBtnText.value countDownNum.value s;if (countDownNum.value 0) {clearInterval(timer);sendBtnText.value 发送验证码;countDownNum.value 60;}}, 1000);};return { sendBtnText, sendCode };
};
逻辑和上面一样,只不过是返回了一个按钮要显示的文本以及一个点击发送验证码调用的函数。然后在组件中使用
import { ref } from vue;
import useCountDown from ../hooks/useCountDown;
const code ref();
const { sendBtnText, sendCode } useCountDown(60);
七、hooks 函数封装细节归纳
1.hooks 函数接收参数写法
写法 1参数通过 props 接收先定义参数类型内部再解构
export function commonRequest(params: Axios.AxiosParams) {let{ url, method, data, responseType json} params
}
写法 2接收传参对象先设置默认值再定义参数类型
interface DeprecationParam {from: string;replacement: string;type: string;
}
export const useDeprecated ({ from, replacement, type API }: DeprecationParam) {}2.解构重命名写法
// setup中const { list:goodsList, getList:getGoodsList } useList(axios.get(/url/get/goods))
const { list:recommendList, getList:getRecommendList } useList(
axios.get(/url/get/recommendGoods)
)
3.KeyboardEvent 为鼠标按键类型
export const useEscapeKeydown (handler: (e: KeyboardEvent) void) {}
八、总结
Vue2 时代 Option Api data、methos、watch.....分开写这种是碎片化的分散的代码一多就容易高耦合维护时来回切换代码是繁琐的
Vue3 时代 Composition Api通过利用各种 Hooks 和自定义 Hooks 将碎片化的响应式变量和方法按功能分块写实现高内聚低耦合。