文档详情

30行代码实现React双向绑定hook的示例代码.docx

发布:2025-05-16约5.96千字共9页下载文档
文本预览下载声明

30行代码实现React双向绑定hook的示例代码

目录使用Proxy代理数据使用useRef创建同一份数据引用添加更新handler去除多次Proxy添加缓存完善代码总结Sandbox示例Vue和MobX中的数据可响应给我们留下了深刻的印象,在React函数组件中我们也可以依赖hooks来实现一个简易好用的useReactive。

看一下我们的目标

constCountDemo=()={

constreactive=useReactive({

count:0,

return(

()={

reactive.count++;

{reactive.count}

/div

};

简单来说就是我们不需要再手动触发setState的handler了,修改数据,组件中的数据就会直接更新。

在Vue中我们实现数据可响应概括来讲需要:

1.解析模板收集依赖

2.发布订阅实现更新

而React函数组件凭借函数的特性这个过程将更加简单,因为函数组件每一次render都会重新执行一遍,我们只需要改变数据之后再触发组件渲染就能达到我们的目的。

因此实现这个自定义hook的核心就是:

1.维护同一份数据

2.劫持对数据的操作

3.在劫持操作中触发组件更新(setState)

使用Proxy代理数据

这个代理模式是实现响应式数据的核心。Vue2.0中使用defineProperty来做数据劫持,现在则是被Proxy模式所替代了,一句话概括defineProperty和proxy的区别就是前者劫持的是属性访问器,而后者可以代理整个对象(Vue3.0,MobX)。

Proxy有多达13种拦截器,我们这次用到的有get,set,delete

constobserver=(initialState,cb)={

constproxy=newProxy(initialState,{

get(target,key,receiver){

constval=Reflect.get(target,key,receiver);

returntypeofval===objectval!==nullobserver(val,cb):val;//递归处理object类型

set(target,key,val){

constret=Reflect.set(target,key,val);

cb();

returnret;

deleteProperty(target,key){

constret=Reflect.deleteProperty(target,key);

cb();

returnret;

returnproxy;

};

上面这个observer完成了对数据的基本操作代理。

这里补充一个知识点:为什么Proxy代理的对象经常搭配Reflect而不是操作符访问?

Reflect更加全面,功能更强大:

只要Proxy对象具有的代理方法,Reflect对象全部具有,以静态方法的形式存在。这些方法能够执行默认行为,无论Proxy怎么修改默认行为,总是可以通过Reflect对应的方法获取默认行为。

比如上文第4行这里Reflect.get(target,key,receiver)咋一看似乎可以和target[key]等价,但实际上不是的看下面的例子,正是由于Reflect的静态方法的第三个参数receiver可以用来指定被调用时的this,所以使用Reflect.get(target,key,receiver)才能如我们预期返回正确结果。

leto={

getb(){

returnthis.a;

leto1=Object.create(

newProxy(o,{

get(target,key,receiver){

returnReflect.get(target,key,receiver);

o1.a=42;

o1.b;//42

leto2=Object.create(

newProxy(o,{

get(target,key){

returntarget[key];

o2.a=42;

o2.b;//undefined

修改某些Object方法的返回结果,

显示全部
相似文档