精读《React PowerPlug 源码》 (3)

By the way, 还监听了 onMouseDown 与 onMouseUp:

export default { bind: { tabIndex: -1, onBlur: () => { if (canBlur) { set(false); } }, onFocus: () => set(true), onMouseDown: () => (canBlur = false), onMouseUp: () => (canBlur = true) } };

可能意图是防止在 mouseDown 时触发 blur,因为 focus 的时机一般是 mouseDown。

2.11. Hover

与 Focus 类似,只是触发时机为 Hover。

用法 <Hover> {({ hovered, bind }) => ( <div {...bind}> You are {hovered ? "hovering" : "not hovering"} this div. </div> )} </Hover> 源码

源码地址

原料:Value

依然利用 Value 组件,value 重命名为 hovered 且初始值为 false,增加了 bind 方法。

bind 方法与 Active、Focus 如出一辙,仅是监听时机变成了 onMouseEnter 和 onMouseLeave。

2.12. Touch

与 Hover 类似,只是触发时机为 Hover。

用法 <Touch> {({ touched, bind }) => ( <div {...bind}> You are {touched ? "touching" : "not touching"} this div. </div> )} </Touch> 源码

源码地址

原料:Value

依然利用 Value 组件,value 重命名为 touched 且初始值为 false,增加了 bind 方法。

bind 方法与 Active、Focus、Hover 如出一辙,仅是监听时机变成了 onTouchStart 和 onTouchEnd。

2.13. Field

与 Value 组件唯一的区别,就是

用法

这个用法和 Value 没区别:

<Field> {({ value, set }) => ( <ControlledField value={value} onChange={e => set(e.target.value)} /> )} </Field>

但是用 bind 更简单:

<Field initial="hello world"> {({ bind }) => <ControlledField {...bind} />} </Field> 源码

源码地址

原料:Value

依然利用 Value 组件,value 保留不变,初始值为 '',增加了 bind 方法,保留 set reset 方法。

与 Value 的唯一区别是,支持了 bind 并封装 onChange 监听,与赋值受控属性 value。

export default { bind: { value, onChange: event => { if (isObject(event) && isObject(event.target)) { set(event.target.value); } else { set(event); } } } }; 2.14. Form

这是一个表单工具,有点类似 Antd 的 Form 组件。

用法 <Form initial={{ firstName: "", lastName: "" }}> {({ field, values }) => ( <form onSubmit={e => { e.preventDefault(); console.log("Form Submission Data:", values); }} > <input type="text" placeholder="Your First Name" {...field("firstName").bind} /> <input type="text" placeholder="Your Last Name" {...field("lastName").bind} /> <input type="submit" value="All Done!" /> </form> )} </Form> 源码

源码地址

原料:Value

依然利用 Value 组件,value 重命名为 values 且初始值为 {},增加了 setValues field 方法,保留 reset 方法。

表单最重要的就是 field 函数,为表单的每一个控件做绑定,同时设置一个表单唯一 key:

export default { field: id => { const value = values[id]; const setValue = updater => typeof updater === "function" ? set(prev => ({ ...prev, [id]: updater(prev[id]) })) : set({ ...values, [id]: updater }); return { value, set: setValue, bind: { value, onChange: event => { if (isObject(event) && isObject(event.target)) { setValue(event.target.value); } else { setValue(event); } } } }; } };

可以看到,为表单的每一项绑定的内容与 Field 组件一样,只是 Form 组件的行为是批量的。

2.15. Interval

Interval 比较有意思,将定时器以 JSX 方式提供出来,并且提供了 stop resume 方法。

用法 <Interval delay={1000}> {({ start, stop }) => ( <> <div>The time is now {new Date().toLocaleTimeString()}</div> <button onClick={() => stop()}>Stop interval</button> <button onClick={() => start()}>Start interval</button> </> )} </Interval> 源码

源码地址

原料:无

提供了 start stop toggle 方法。

实现方式是,在组件内部维护一个 Interval 定时器,实现了组件更新、销毁时的计时器更新、销毁操作,可以认为这种定时器的生命周期绑定了 React 组件的生命周期,不用担心销毁和更新的问题。

具体逻辑就不列举了,利用 setInterval clearInterval 函数基本上就可以了。

2.16. Compose

Compose 也是个有趣的组件,可以将上面提到的任意多个组件组合使用。

用法 <Compose components={[Counter, Toggle]}> {(counter, toggle) => ( <ProductCard {...productInfo} favorite={toggle.on} onFavorite={toggle.toggle} count={counter.count} onAdd={counter.inc} onRemove={counter.dec} /> )} </Compose> 源码

源码地址

原料:无

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywxyy.html