前言
在vue中,提起代码复用,最常使用的三驾马车便是Component、Hooks 以及 Mixins,本文将着重介绍Mixins与Hooks的区别,从而更好的拥抱Hooks生态。
Mixins
我们在开发过程中,常常会遇到重复的代码逻辑片段,mixins(混入)就是将这部分相同的逻辑片段,单独抽离出来,进行封装。通过将mixins引入需要使用该段逻辑的页面,从而实现一段代码,多页面复用的效果。
mixins的特点:
顾名思义,mixins(混入),即将当前的代码片段混入到的父组件中
- mixins与父组件共用生命周期函数,mixins中定义的生命周期部分,将自动整合进父组件的生命周期中
- 若mixins中定义的变量与父组件重名,将优先采用父组件中定义的变量
- 若mixins与其他引入父组件中的mixins组件中定义的变量重名,将按照mixins的引入顺序,采用后引入者中定义的变量
mixins的使用
1. 在Vue2中使用
//mixins文件
export const testMixins = {
data(){
return {
list:[1,2,3,4,5],
msg:"我是mixins中的数据"
}
},
computed:{
},
methods:{
total(){
let sum = list.reduce((pre,cur)=>{
return pre+cur
},0)
return sum
},
getList(){
return this.list
}
},
}
在父组件中引入mixins
<!-- 父组件引入mixins -->
<template>
<div>
<div>我是父组件</div>
<div>{{msg}}</div>
</div>
</template>
<script>
import testMixins from './testMixins'
export default {
mixins:[testMixins],
data() {
return {
name:'father',
count:0
}
},
mounted() {
console.log('我是父组件中的mounted()')
this.count = total()
},
}
</script>
<style lang="'scss" scoped>
</style>
由于在vue3中强烈推荐使用hooks替代mixins使用,因此此处不再赘述mixins的vue3写法。
mixins的缺点:
通过上述的使用示例,我们不难发现mixins在使用中存在以下致命缺陷
- 由于mixins混入的特性,其中定义的变量相当于隐式引入了父组件,从而导致变量难以定位到其定义的具体位置
- 若父组件仅需要mixins中某一小段逻辑,通过mixins的方式还是只能将整个mixins文件引入后进行使用,无形中增加了无效代码的引用
- 最致命的便是多mixins引入重名的情况
例如:当前页面引入了多个mixins,每个mixins内均定义了一个变量名为list,我既想使用mixinsA中的list又想使用mixinsB中的list就成为了一个令人头疼的问题。
Hooks
很显然,越来越多的框架开发者们也注意到了mixins的上述缺陷,因此急需一种新的代码复用逻辑的优化方案,由此基于hooks实现代码复用的方式横空出世。
所谓hooks直译过来便是钩子函数。我们可以将mixins理解为一个将<script></script>标签部分的js逻辑代码片段文件,而hooks正如其中文译名,不同于mixins其本质上是一个可以复用的函数,其在vue3的setup()中调用。
mixins的使用
1. 在Vue3中的基础用法
在项目路径下新建一个名为hooks的文件夹,在里面新建名为test.js的一个hooks文件
注意hooks组件的命名规范为,use+hooks功能名的大驼峰命名方式,例如:需要封装一个table复用的hooks,则命名为useTable.js
//useTest.js
import { ref } from "vue";
export default function useTest() {
//定义变量
const list = ref([1, 2, 3, 4, 5]);
const msg = ref("我是hooks中的数据");
//使用生命周期函数
onMounted(() => {
console.log("我是hooks中定义的onMounted()");
});
//定义方法
const total = () => {
let sum = list.reduce((pre, cur) => {
return pre + cur;
}, 0);
return sum;
};
const getList = () => {
return list.value
};
//将需要使用的数据和函数暴露出去
return {
list,
msg,
total,
getList
};
}
在父组件中引入hooks
<!--父组件中引入hooks -->
<template>
<div>
<div>我是父组件的数据</div>
<!-- 使用hooks中的变量 -->
<div>{{msg}}</div>
<!-- 使用hooks中的方法进行求值 -->
<div>{{count}}</div>
</div>
</template>
<script lang="ts" setup>
import useTest from './hooks/useTest.js'
//需按需求自由hooks中的变量和方法
const {msg,total,list} = useTest()
const count = ref(total)
</script>
<style lang="scss" scoped>
</style>
hooks的优势和不足:
优势:
hooks让开发者可以根据当前页面的需求,选择性的引入hooks中的变量和方法,减小无效代码的复用- 不同于
mixins,hooks中引入的变量通过hooks名.变量名的方式进行使用,从而避免了变量重名的问题,即使变量重名,只要对应的hooks组件不重名,就可以通过hooks名.变量名的方式进区分。
不足:
- 由于
hooks本身是一个函数,因此调用hooks中定义的方法会产生闭包,大量滥用hooks,不可避免的存在一定的内存泄露问题,不过大部分情况下hook的表现还是非常优秀的。