前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React Hook 和 Vue Hook

React Hook 和 Vue Hook

原创
作者头像
愤怒的小鸟
修改2021-01-27 18:10:55
2.1K0
修改2021-01-27 18:10:55
举报
文章被收录于专栏:web share

一、Hook 和 Mixin & HOC 对比

「Mixin & HOC 模式」所带来的缺点:

  1. 渲染上下文中公开的属性的来源不清楚。 例如,当使用多个 mixin 读取组件的模板时,可能很难确定从哪个 mixin 注入了特定的属性。
  2. 命名空间冲突。 Mixins 可能会在属性和方法名称上发生冲突,而 HOC 可能会在预期的 prop 名称上发生冲突。
  3. 性能问题,HOC 和无渲染组件需要额外的有状态组件实例,这会降低性能。

而 「Hook」模式带来的好处:

  1. 暴露给模板的属性具有明确的来源,因为它们是从 Hook 函数返回的值。
  2. Hook 函数返回的值可以任意命名,因此不会发生名称空间冲突。
  3. 没有创建仅用于逻辑重用的不必要的组件实例。

二、React Hook 和 Vue Hook 对比

其实 React Hook 的限制非常多:

  1. 不要在循环,条件或嵌套函数中调用 Hook
  2. 确保总是在你的 React 函数的最顶层调用他们。
  3. 遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。

而 Vue 带来的不同在于:

  1. 与 React Hooks 相同级别的逻辑组合功能,但有一些重要的区别。 与 React Hook 不同,setup 函数仅被调用一次,这在性能上比较占优。
  2. 对调用顺序没什么要求,每次渲染中不会反复调用 Hook 函数,产生的的 GC 压力较小。
  3. 不必考虑几乎总是需要 useCallback 的问题,以防止传递函数prop给子组件的引用变化,导致无必要的重新渲染。
  4. React Hook 有臭名昭著的闭包陷阱问题,如果用户忘记传递正确的依赖项数组,useEffect 和 useMemo 可能会捕获过时的变量,这不受此问题的影响。 Vue 的自动依赖关系跟踪确保观察者和计算值始终正确无误。
  5. React Hook 里的「依赖」是需要你去手动声明的。

三、React Hooks 中的闭包问题

Hooks 严重依赖于 JS 闭包,但是闭包有时很棘手,当咱们使用一个有多种副作用和状态管理的 React 组件时,可能会遇到的一个问题是过时的闭包

过时的闭包捕获具有过时值的变量:

代码语言:javascript
复制
function createIncrement(i) {
  let value = 0;
  function increment() {
    value += i;
    console.log(value);
    const message = `Current value is ${value}`;
    return function logValue() {
      console.log(message);
    };
  }
  
  return increment;
}

const inc = createIncrement(1);
const log = inc(); // 打印 1
inc();             // 打印 2
inc();             // 打印 3
// 无法正确工作
log();             // 打印 "Current value is 1"

修复过时闭包的问题:

1. 使用新的闭包

解决过时闭包的第一种方法是找到捕获最新变量的闭包。

找到捕获了最新 message 变量的闭包,就是从最后一次调用 inc() 返回的闭包。

代码语言:javascript
复制
const inc = createIncrement(1);

inc();  // 打印 1
inc();  // 打印 2
const latestLog = inc(); // 打印 3
// 正常工作
latestLog(); // 打印 "Current value is 3"

latestLog 捕获的 message 变量具有最新的的值 “Current value is 3”。

Hooks 实现假设在组件重新渲染之间,作为 Hook 回调提供的最新闭包(例如 useEffect(callback)) 已经从组件的函数作用域捕获了最新的变量。

2. 关闭已更改的变量

第二种方法是让logValue()直接使用 value

代码语言:javascript
复制
function createIncrementFixed(i) {
  let value = 0;
  function increment() {
    value += i;
    console.log(value);
    return function logValue() {
      const message = `Current value is ${value}`;
      console.log(message);
    };
  }
  
  return increment;
}

const inc = createIncrementFixed(1);
const log = inc(); // 打印 1
inc();             // 打印 2
inc();             // 打印 3
// 正常工作
log();             // 打印 "Current value is 3"

logValue() 关闭 createIncrementFixed() 作用域内的 value 变量。log() 现在打印正确的消息“Current value is 3”。

React Hook解决过时闭包问题的方法:

  • 解决过时闭包的一个有效方法是正确设置 React Hook 的依赖项。
  • 对于过时的状态,使用函数方式更新状态。
  • 安装 eslint-plugin-react-hooks,检测被遗忘的依赖项。
代码语言:javascript
复制
  // 正确设置 Hook 的依赖项
  const [count, setCount] = useState(0);

  useEffect(function() {
    const id = setInterval(function log() {
      console.log(`Count is: ${count}`);
    }, 2000);
    return function() {
      clearInterval(id);
    }
  }, [count]);
代码语言:javascript
复制
  // 函数方式更新状态
  const [count, setCount] = useState(0);

  function handleClickAsync() {
    setTimeout(function delay() {
      setCount(count => count + 1); 
    }, 1000);
  }

  function handleClickSync() {
    setCount(count + 1);
  }

.

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Hook 和 Mixin & HOC 对比
    • 「Mixin & HOC 模式」所带来的缺点:
      • 而 「Hook」模式带来的好处:
      • 二、React Hook 和 Vue Hook 对比
        • 其实 React Hook 的限制非常多:
          • 而 Vue 带来的不同在于:
          • 三、React Hooks 中的闭包问题
            • 过时的闭包捕获具有过时值的变量:
              • 修复过时闭包的问题:
                • React Hook解决过时闭包问题的方法:
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档