hooks
以前在react中写hooks,就一直不理解其中实现数据响应的函数,只能死记硬背模板代码实现简单业务
兜兜转转,vue3还是绕不开这个问题
- 从第一个实例开始
function useMouse(){
const x = ref(0)
const y = ref(0)
...
return {x,y}
}
//引用
const { x, y } = useMouse()
跟着写一遍,没有任何问题,通过加上业务代码可以实现,鼠标滑动页面实时更新坐标数据
- 再来第二个实例
function useLocalStorage(name,initValue){
const data = ref(JSON.parse(localStorage.getItem(name))||initValue)
watchEffect(() => {
localStorage.setItem(name, JSON.stringify(data.value))
})
return data
}
//引用
const data = useLocalStorage('name',[])
本来也没有任何问题,但我在看实例之前,先按自己的理解实现了一遍
function useLocalStorage(name,initValue){
...
//get(){} //这部分代码后面被废弃,改成上面的ref写法
set(value){
localStorage.setItem(name, JSON.stringify(value))
}
return {data,set}
}
//引用
const {list,set} = useLocalStorage('name',[]) //bug在这里
set(newValue)
由于页面还有其他功能代码,在引用时对返回值重命名为list了,导致这个list参数一直是undefine报错,
对比第一个实例后,发现问题出在返回值上,如下修改后正常
const { data : list, set } = useLocalStorage('name',[]) //引用一个return出来的对象时字段需要对应
这种写法目前的教程实例还没用到,是以前写react从其他小伙伴那里学习到的,于是思考react与vue之间的联系
找bug过程中, 一开始以为是set中localStorage赋值有问题,又因为其他的引用问题,这个set方法一直被vscode报错,所以一直在怀疑这个set的实现,其实它的写法和引用本身没有任何问题。
我一直在纠结,是因为一开始自己的思路是通过手动get和set来实现,担心这种写法与hooks不兼容。
事实上vue3兼容性挺高的,毕竟连ref,watch都可以直接在js中引用
中间还借助了一下chatgpt的神秘力量,帮助我用vue和react两种方式实现了一下类似的update功能,才确认我的写法没问题,并且发现两种语言的实现代码几乎完全一样
虽然最后也没有使用这种写法,这里set方法的问题其实在于不够抽象
抽象
重新梳理一下 ~
- 首先我们通过ref声明了一个参数 xx(
命名不重要)
const xx = ref(initVal)
- 然后通过watch监听xx的数据变化,实现具体业务
watchEffect(() => {
...
})
- 还可以暴露一个方法出去,实现自定义功能
...
function update(val){}
return { ..., update }
通过这一套逻辑,根据具体业务,就可以封装自己的useXX方法了
响应式
能够抽离业务,实现这套逻辑,主要归功于vue3的响应式实现
本质上响应式就是get和set,但是有了ref和reacttive等方法,我们可以完全忽略掉get和set,默认这个数据就是一个响应式的,再借助watch等api直接写功能
这里还有个收获,就是对于ref,reactive的理解,原来只把它当成一种vue3的特殊语法。
每种语言都有自己的一套实现原理,在完全不理解的情况下,照着模板写就完事了。
现在我把它当成一种方法,就像上面的update()和set(),当作是vue暴露出来的一个hooks函数,这个函数实现了一套响应式的方法,然后return了一个data数据被我们接收
function ref(initVal){
let data
...
return data
}
//引用
const x = ref(0)
然后我们在此之上,又进行一次封装,实现useXX函数。人生无常,大肠包小肠。
总结
感受就是学习vue3,需要深入理解响应式,毕竟这也是与react主要区别
然后这篇文章就是通过记录一次失败的封装,初步理解了hooks