vue3响应式与hooks抽象性

162 阅读3分钟
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,但是有了refreacttive等方法,我们可以完全忽略掉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