vue3学习之hook
由于使用vue3.2已经有段时间,对于setup-api的应用也有了基础的认识,最近一直疑惑的一个问题就是作者为什么从2x 升级到3x 直接改变了vue项目文件的形态。要知道这样做会增加vue的学习成本,那么就必然是老版本有痛点,新版本有优势。在3x版本被重点提及的hook又是什么?如何使用?我们一起来探讨。
一、Hook是什么?
首先我们来看看官方对hook的定义:
当构建前端应用时,我们常常需要复用公共任务的逻辑。例如为了在不同地方格式化时间,我们可能会抽取一个可复用的日期格式化函数。这个函数封装了无状态的逻辑:它在接收一些输入后立刻返回所期望的输出。
很清晰明了的说明了hook是做什么的,但是又觉得有什么不对的地方,这不是和2x版本的mixin的功能有些相似么?那接下来我们写一个功能对比下看看。
二、编写自己的hook
使用2x实现联动选择城市功能
<!-- html -->
<template>
<div style="padding:100px 40%">
联动选择省市
<el-select v-model="province" placeholder="选择省份">
<el-option v-for="(item,index) in provinceList" :key="index" :value="item" :label="item">
</el-option>
</el-select>
<el-select v-model="city" placeholder="选择市">
<el-option v-for="(item, index) in cityList" :key="index" :value="item" :label="item">
</el-option>
</el-select>
</div>
</template>
// js 部分
export default {
data () {
return {
province: '',
city: '',
provinceList: [],
cityList: []
}
},
mounted () {
this.getProvinceList()
},
watch: {
province () {
this.getCityList()
}
},
methods: {
getProvinceList () {
this.provinceList = ['河南', '安徽', '西安', '杭州']
},
getCityList () {
this.city = ''
let data = {
'河南': ['郑州', '洛阳', '周口', '开封', '商丘'],
'安徽': ['合肥', '阜阳', '六安'],
'西安': ['西安', '宝鸡', '延安'],
}
this.cityList = data[this.province]
}
}
}
抽离封装mixin
export default {
data () {
return {
province: '',
city: '',
provinceList: [],
cityList: []
}
},
mounted () {
this.getProvinceList()
},
watch: {
province () {
this.getCityList()
}
},
methods: {
getProvinceList () {
this.provinceList = ['河南', '安徽', '西安', '杭州']
},
getCityList () {
this.city = ''
let data = {
'河南': ['郑州', '洛阳', '周口', '开封', '商丘'],
'安徽': ['合肥', '阜阳', '六安'],
'西安': ['西安', '宝鸡', '延安'],
}
this.cityList = data[this.province]
}
}
}
import mixin from './mixin'
export default {
mixins: [mixin],
data () {
return {
// 其他数据
}
},
mounted () {
// 编写其他逻辑
}
}
官方hook Demo
使用组合式 API 实现鼠标跟踪功能
<script setup>
// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'
// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
// 被组合式函数封装和管理的状态
const x = ref(0)
const y = ref(0)
// 组合式函数可以随时更改其状态。
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
// 一个组合式函数也可以挂靠在所属组件的生命周期上
// 来启动和卸载副作用
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
// 通过返回值暴露所管理的状态
return { x, y }
}
</script>
<script setup>
import { useMouse } from './mouse.js'
const { x, y } = useMouse()
</script>
<template>Mouse position is at: {{ x }}, {{ y }}</template>
编写自己的联动选择城市hook
import {ref, onMounted, watch} from 'vue'
export const usePeovicenAndCity = () => {
// province数据相关
const province = ref('')
const provinceList = ref([])
const getProvinceList = () => {
provinceList.value = ['河南', '安徽', '西安', '杭州']
}
watch(province, () => {
getCityList()
})
// city数据相关
const city = ref('')
const cityList = ref([])
const getCityList = () => {
city.value = ''
let data = {
'河南': ['郑州', '洛阳', '周口', '开封', '商丘'],
'安徽': ['合肥', '阜阳', '六安'],
'西安': ['西安', '宝鸡', '延安'],
}
cityList.value = data[province.value]
}
// mounted 调取省份数据
onMounted(() => {
getProvinceList()
})
return {province, city, provinceList, cityList}
}
import {ref} from 'vue'
import {usePeovicenAndCity} from './hook'
let {province, city, provinceList, cityList} = usePeovicenAndCity()
三、hook与mixin的对比
从上面的代码实现来看,mixin复用通用代码看起来好像更优雅,简洁。那么我们对比下页面有多个复用的情况。
mixin
import mixin1 from './mixin1'
import mixin2 from './mixin2'
import mixin3 from './mixin3'
import mixin4 from './mixin4'
export default {
mixins: [mixin1,mixin2,mixin3,mixin4],
data () {
return {
// 其他数据
}
},
watch: {
key () {
// do something
}
}
}
hook
import {ref} from 'vue'
import {fun1, fun2, fun3, fun4,} from './hook'
let {data1, a1} = fun1()
let {data2, a2} = fun2()
let {data3, a3} = fun3()
let {data4, a4} = fun4()
如果页面上某个数据异常,而这个数据是从mixin里面获取的,那么就需要在多个mixin里面一点点找,如果项目庞大的话,这将是个灾难。
对比3x的hook数据源清晰明了,每个数据源都能找到对应的代码片段。
四、vue3学习和项目迁移(个人理解):
1.3x版本的优势
复用相同的逻辑太舒服啦,一个功能模块的代码都在一起,不用上下来回找。
2.3x版本的问题
1、.value的赋值/访问形式太难受了,希望官方后期可以解决;
2、如果有老项目迁移,需要开发者付出一部分精力去学习,对于项目来讲成本增加了很多
3.阅读性和维护
首先从项目的阅读性和维护难度来讲,2x版本的下限高,上限低。3x版本的上限很高,下限很低理想状态下 从上至下的代码可以简化为 功能A-功能B-功能C… 各个功能之间没有耦合的代码,而2x版本的代码功能是分散在data、watch、methods 各个模块之间的,所以3x版本相较于2x上限会高很多,同样下限也会低与2x, 因为各种api没有了约束,对于不熟悉的开发者会造成功能代码更乱等问题。
4.哪些项目适合使用3x
新项目:综合学习成本和项目复杂度来决定。新的版本必定要有一定的学习成本,这个时间对于项目来讲