[关闭]
@Rays 2019-02-15T15:21:35.000000Z 字数 2544 阅读 1365

TNG-Hooks:在标准函数中重用和组合有状态逻辑

未分类


摘要: 最新发布的TNG-Hooks软件库,支持开发人员在标准(regular)独立函数中添加适用逻辑。这些逻辑通常是有状态(stateful)并有效(effectful)的,例如查询远程数据库、访问范围之外的上下文数据等。钩子函数(Hook)提供代码重用和代码组合,有助于实现规模更小、更易于维护并且更稳定的代码库。

作者: Bruno Couriol

正文:

最新发布的TNG-Hooks软件库,支持开发人员在标准(regular)独立函数中添加适用逻辑。这些逻辑通常是有状态(stateful)并有效(effectful)的,例如查询远程数据库、访问范围之外的上下文数据等。钩子函数(Hook)提供代码重用和代码组合,有助于实现规模更小、更易于维护并且更稳定的代码库。

在去年的React大会上,React发布的React Hooks令各个开发者社区大为赞叹。开发人员可使用Reack Hooks,将有状态或有效计算完全抽象为函数形式,进而在React函数组件中得到重用和组合。先前用单独的纯计算函数添加效果和状态的做法,就是使用ES类而非函数。对于开发经验不足的开发人员而言,使用函数要比ES类更易于实现代码组合。此外,使用ES类会导致代码零散,有效逻辑位需要复制到各种各样的方法中。TNG-Hooks中在降低对React依赖的同时,利用了React Hooks的优点。

为了最小化React函数组件,TNG引入了一种称为“挂钩函数”Articulated Functions的概念。挂钩函数需要满足两个条件。首先,挂钩函数在被调用前,需要包裹一个TNG修饰器(decorator)。其次,挂钩函数可在执行过程中的某处调用钩子函数。

下面给出一个例子代码。其中,TNG函数作为修饰器,useState是一个钩子函数,而hit就是一个挂钩函数。

  1. function hit() {
  2. var [count,updateCount] = useState(0);
  3. count++;
  4. updateCount(count);
  5. console.log(`Hit count: ${count}`);
  6. }
  7. hit = TNG(hit);
  8. hit(); // Hit计数:1
  9. hit(); // Hit计数:2
  10. hit(); // Hit计数:3

上例中,hit函数被多次调用,每次调用后返回不同的值。由此,我们称hit函数是一个有状态函数。钩子函数useState用于抽象本地状态管理,包括检索、存储和状态更新等。钩子函数将状态变量count初始化为0,并返回该变量值。函数updateCount对该状态变量做更新。

TNG-Hooks函数库还提供了useReduceruseEffectuseMemouseCallbackuseRef等钩子函数,每个钩子函数抽象了不同的有状态计算或有效计算。

此外,TNG软件库提供模仿React Custom HooksTNG Custom Hooks,支持自定义钩子函数。开发人员可使用Custom Hooks,通过重用现的有钩子函数去定义自己的钩子函数。TNG Custom Hooks并非铰链函数,而是标准JavaScript函数,在执行中某处调用挂钩函数。TNG Custom Hooks本身的调用也必须在挂钩函数中。

  1. // useHitCounter定义了一个Custom Hook,而非挂钩函数。
  2. function useHitCounter() {
  3. // 继承TNG钩子函数的上下文。
  4. var [count,updateCount] = useState(0);
  5. count++;
  6. updateCount(count);
  7. return count;
  8. }
  9. // 两次挂钩到TNG(..),每次均为点击按钮句柄(handler)。
  10. function onClick(evt) {
  11. // 使用Custom Hook。
  12. var hitCount = useHitCounter();
  13. console.log(console.log(`Button #${evt.target.id}: ${hitCount}`);
  14. }
  15. var fooBtn = document.getElementById("foo-btn");
  16. var barBtn = document.getElementById("bar-btn");
  17. // 将每个点击句柄挂钩到`onClick()`。
  18. fooBtn.addEventListener("click",TNG(onClick),false);
  19. barBtn.addEventListener("click",TNG(onClick),false);

上例展示的Custom Hook函数useHitCounter,并未定义为挂钩函数,它重用了给定的钩子函数useStateuseHitCounter本身被挂钩函数onClick调用。fooBtnbarBtn分别重用了同一自定义有状态逻辑useHitCounter,该逻辑嵌在onClick事件句柄中。

TNG Hooks虽然参考了React项目,但它是一个全新的项目。TNG-Hooks软件库的作者Kyle Simpson给出了如下阐述:

TNG Hooks是一个独立的项目,它具有自身的考虑和特定行为。TNG将继续保持与React Hooks的相似风格,但也会保持适当的差异。

与React Hooks一样,挂钩函数和钩子函数必须遵守一些调用规则。当前,并没有任何强制符合上述规则的机制,开发人员在违反这些规则时也不会给出警告。这可能会导致一些出错行为难以调试。此外,React Hooks是一种实验性的全新技术,部分注意事项仍未成型。尽管TNG Hooks考虑了React Hooks的一些经验教训,但还需要做更多的测试去验证其最佳实践和陷坑。

TNG Hooks支持通过tng-hooks npm package安装,据该软件包自身宣称,其测试代码覆盖率达100%。

TNG Hooks以MIT许可开源发布。欢迎通过TNG-Hooks的GitHub项目给出反馈和贡献。

查看英文原文: TNG-Hooks: Reuse and Compose Stateful, Effectful Logic within Regular Functions

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注