当前位置: 首页 > news >正文

Vue3 Hooks 对比 Vue2 Mixins 两者之间的区别?

在Vue生态中,"Hooks"这个概念随着Vue3的发布而变得火热。但很多开发者可能会有疑问:Vue2中不是也有"混入"(mixins)吗?它们有什么区别?为什么Vue3要引入Hooks?

本文将深入探讨Vue3中Hooks的实现方式,并与Vue2的Mixins进行对比,通过一个实际的例子,让你直观地理解这场"逻辑复用革命"的本质。

一、啥是 Hooks?

Hooks 就是一个带状态的函数。

啥意思?就是普通函数只管算东西,算完就完事了。但 Hooks 不一样,它内部可以有自己的"记忆"(响应式数据),还能在组件卸载的时候自己打扫卫生(清理定时器啥的)。

打个比方:

  • 普通函数就像一次性筷子,用完就扔

  • Hooks 就像能反复使用的餐具,每次用都能记住上次的状态

二、拿个真实场景说话

假设我们要做个登录页面,有个"发送验证码"的按钮,点完之后要倒计时60秒,这60秒内按钮是灰色的点不了,倒计时结束按钮才能再点。

这个功能在很多地方都会用到,比如注册、找回密码等等,所以我们肯定想把它抽出来复用。

三、看看 Vue2 咋搞的(Mixins 版本)

先写个 Mixin

// countdownMixin.js
export default {data() {return {countdownSeconds: 60,  // 倒计时秒数isCounting: false,     // 是否正在倒计时timerId: null,         // 定时器放这儿buttonText: '发送验证码' // 按钮上显示的字}},methods: {startCountdown() {this.isCounting = truethis.buttonText = `${this.countdownSeconds}秒后重发`this.timerId = setInterval(() => {this.countdownSeconds--if (this.countdownSeconds <= 0) {// 倒计时结束clearInterval(this.timerId)this.isCounting = falsethis.buttonText = '重新发送'this.countdownSeconds = 60} else {this.buttonText = `${this.countdownSeconds}秒后重发`}}, 1000)}},// 组件销毁时清理定时器,防止内存泄漏beforeDestroy() {if (this.timerId) {clearInterval(this.timerId)}}
}

  

在组件里用这个 Mixin

vue2
<template><div><input type="text" v-model="phone" placeholder="手机号" /><button @click="sendCode" :disabled="isCounting">{{ buttonText }}</button></div>
</template><script>
import countdownMixin from './countdownMixin'export default {mixins: [countdownMixin],  // 引入mixindata() {return {phone: '',}},methods: {sendCode() {console.log('发送验证码到', this.phone)this.startCountdown()}}
}
</script>

  

这样写有啥问题?

问题1:数据从哪来的?
新来的同事看到代码里的 isCountingbuttonText,肯定一脸懵:这变量哪冒出来的?得去翻 mixin 文件才能知道。

问题2:命名冲突
假如我组件里本来就有个 isCounting 变量,想记录别的状态,完蛋,跟 mixin 里的冲突了。谁后加载谁覆盖,bug 就偷偷出现了。

问题3:方法被覆盖
要是不小心在组件里也写了个 startCountdown 方法,mixin 里的就被覆盖了,倒计时功能就失效了。

问题4:不好找 bug
倒计时出问题了,你得去 mixin 文件里找原因,但 mixin 可能被十几个地方用着,改起来提心吊胆。

四、再看看 Vue3 咋搞的(Hooks 版本)

先写个 Hook

javascript
// useCountdown.js
import { ref, computed, onUnmounted } from 'vue'export function useCountdown(initialSeconds = 60) {// 所有的状态都写在里面const seconds = ref(initialSeconds)  // 当前剩余秒数const isActive = ref(false)          // 是否正在倒计时let timer = null                      // 定时器// 按钮上显示的文字(计算属性)const buttonText = computed(() => {if (isActive.value) {return `${seconds.value}秒后重发`}return '发送验证码'})// 开始倒计时const start = () => {if (isActive.value) returnisActive.value = truetimer = setInterval(() => {if (seconds.value > 0) {seconds.value--} else {// 倒计时结束clearInterval(timer)isActive.value = falseseconds.value = initialSeconds}}, 1000)}// 组件卸载时自动清理(不用你操心)onUnmounted(() => {if (timer) {clearInterval(timer)}})// 明确告诉你:我只返回这些东西return {seconds,isActive,buttonText,start}
}

  

在组件里用这个 Hook

vue3
<template><div><input type="text" v-model="phone" placeholder="手机号" /><button @click="sendCode" :disabled="isActive">{{ buttonText }}</button></div>
</template><script setup>
import { ref } from 'vue'
import { useCountdown } from './useCountdown'// 组件自己的数据
const phone = ref('')// 使用倒计时功能
// 这里清清楚楚写着:我要用 isActive、buttonText、start
const { isActive, buttonText, start } = useCountdown(60)// 可以自己定义一个 isCounting,完全不冲突!
const isCounting = ref(false)  // 这是我自己的状态,跟倒计时没关系const sendCode = () => {console.log('发送验证码到', phone.value)start()  // 开始倒计时
}// 如果需要用两个倒计时?完全没问题!
const code1 = useCountdown(60)   // 手机验证码倒计时
const code2 = useCountdown(120)  // 邮箱验证码倒计时,互不干扰
</script>

  

这样写有啥好处?

好处1:代码出处一目了然
看到 isActive 就知道是从 useCountdown 来的,不用到处找。

好处2:随便命名不怕冲突
想叫啥就叫啥,还可以重命名:

javascript
const { isActive: codeActive, buttonText: codeBtnText } = useCountdown()

好处3:按需取用
只要 isActive 和 buttonText,别的不要?那就别解构出来,完美。

好处4:多个实例独立
想用几个倒计时就用几个,各自管各自的,谁也不影响谁。

五、一句话总结区别

 
对比MixinsHooks
数据来源 神神秘秘,不知道哪来的 明明白白,从函数返回的
命名 容易打架 随便取,不怕冲突
复用 牵一发可能动全身 各用各的,互不干扰
调试 得翻好几个文件 就在眼前,好找

 

http://www.jsqmd.com/news/417471/

相关文章:

  • 2026年香薰市场风向标:哪些蜡烛OEM公司值得关注,香薰纸片/天然植物精油香氛/别墅香氛,香薰ODM公司推荐排行榜 - 品牌推荐师
  • 简单理解:文档类型doc 和 docx的区别
  • 工业脱碳:Calderion、WenCo和Terravent投资Graforce,推动等离子体热解技术全球规模化应用
  • 2026天津国际高中哪家强?5所热门学校与升学率高的国际高中推荐 - 品牌2025
  • 2026金华义乌AI优化服务商TOP4权威评测:品牌智能化增长优选指南 - 呼呼拉呼
  • 2026年推荐治疗心脏瓣膜疾病的医院参考 - 品牌排行榜
  • Spring全家桶全彩学习进阶笔记(终极版)
  • 《百度最新财报:2025年营收1291亿元 四季度AI业务收入占比43%》
  • 电天下搜索列表数据接口深度实战:AI搜索协议+会员权限+电力数据合规方案
  • Black Hat Asia 2026将揭晓有关人工智能威胁与供应链漏洞的突破性研究成果
  • impression?
  • 2026年天津国际高中推荐汇总,天津国际高中怎么选及比较知名的天津国际高中一览 - 品牌2025
  • 专科生收藏!千笔,口碑爆棚的AI论文网站
  • 工正主流RIP适配UV导带机推荐,有哪些优势? - 工业品网
  • 2026推荐上海主动脉夹层治疗的医院有哪些? - 品牌排行榜
  • 2026年逆流式冷却塔填料/浊环水循环/网格填料/网格板厂家优选: 济源市灵辉环保科技专注工业冷却核心组件 - 品牌推荐官
  • 总结北京瓷砖品牌,哪家瓷砖定制厂家的服务和性价比更高? - 工业推荐榜
  • 【软件】NFS部署
  • 可靠流延机专业制造商有哪些,该如何进行选购和对比 - myqiye
  • GAMES202课程资源
  • Rust 编程实战练习
  • 分析慢走丝机床品牌,为你推荐性价比高的厂家 - 工业设备
  • 2026食用面碱优质品牌揭秘,市面上头部食用纯碱公司推荐排行榜,小酥肉淀粉/超级生粉,食用面碱供应商推荐榜单 - 品牌推荐师
  • ubuntu 可以通过终端命令直接给串口发生数据吗
  • 专科生必看!行业天花板级的AI论文工具 —— 千笔AI
  • 探讨河北地区预应力高强钢筋拉丝机价格多少钱? - 工业品网
  • 2026年涂装生产线厂家推荐,苏力机械性价比怎么样? - 工业品牌热点
  • 口碑好的UPS电源服务商有哪些,金盛通科技服务靠谱不 - mypinpai
  • 天津艺豪创新能力、可信度及口碑揭秘,装修选它性价比高吗 - 工业推荐榜
  • 【命令】yum相关操作