当前位置 博文首页 > apolis:聊聊 React

    apolis:聊聊 React

    作者:apolis 时间:2021-01-20 10:06

    都说 React 开发效率高,但效率高在哪呢?来细看看。

    都说 React 开发效率高,但效率高在哪呢?来细看看。

    用 d3 写一个 List:

    const renderList = data => {
      d3.select("ul")
        .selectAll("li")
        .data(data, d => d.id)
        .join(
          enter => enter.append("li").text(d => d.text),
          update => update.text(d => d.text),
          exit => exit.remove()
        );
    };
    

    d3 把 view 和 data 的关系分为 3 种:

    • enter:有 data 没 view
    • update:有 data 有 view
    • exit:有 view 没 data

    数据更新,开发者需考虑「新 view」对比「老 view」,新增的「enter」、更新的「update」、减少的「exit」要怎么处理。


    用 React 来写:

    const List = ({ data }) => {
      return (
        <ul>
          {data.map(d => (
            <li key={d.id}>{d.text}</li>
          ))}
        </ul>
      );
    };
    

    数据更新,开发者只需考虑「新 view」是什么样,不用考虑怎么把「老 view」变成「新 view」,比 d3 简单。


    React 是不是比 d3 好用?

    答:不一定,要看场景。React 框架把「新增的、更新的、减少的处理」都做了,开发者没法干预。但如果你想做一些动画,需要精细控制「新增的、更新的、减少的」,React 就不如 d3 好用了。

    再看 React 代码:

    const List = ({ data }) => {
      return (
        <ul>
          {data.map(d => (
            <li key={d.id}>{d.text}</li>
          ))}
        </ul>
      );
    };
    

    React 把组件简化成了一个函数,data -> view。组件就是函数,意味着函数可以怎么玩,组件就可以怎么玩。

    • 函数内调用别的函数

      function a() {}
      function b() {}
      
      function c() {
        a();
        b();
      }
      
      function A() {}
      function B() {}
      
      function C() {
        return (
          <div>
            <A />
            <B />
          </div>
        );
      }
      
    • 函数的返回值作为别的函数的传参

      function a() {}
      function b(arg) {}
      
      function c() {
        b(a());
      }
      
      function A() {}
      function B({ children }) {
        return <div>{children}</div>;
      }
      
      function C() {
        return (
          <B>
            <A />
          </B>
        );
      }
      
    • 高阶函数

      function memoize(fn) {
        const cache = {};
        return arg => {
          if (cache[arg]) return cache[arg];
          else {
            const result = fn(arg);
            cache[arg] = result;
            return result;
          }
        };
      }
      
      const memoizedSqrt = memoize(Math.sqrt);
      
      const A = () => {};
      const wrapper = Cmp => {};
      const WrappedA = wrapper(A);
      
    • Continuation,或者叫 Callback。Callback 的特点是:等时机成熟后才执行。

      const handler = () => {};
      button.addEventListener("click", handler);
      
      // Context Consumer
      <ThemeContext.Consumer>
        {theme => <Cmp theme={theme} />}
      </ThemeContext.Consumer>
      
      // Render Props
      const MouseTracker = Cmp => {
        return (
          <Mouse
            render={mouse => <Cmp mouse={mouse} />}
          />
        );
      };
      
    • 递归

      const factorial = n => {
        if (n === 1) return 1;
        else return n * factorial(n - 1);
      };
      
      const Tree = ({ data }) => (
        <ul>
          {data.map(d => (
            <li key={d.id}>
              {d.text}
              {d.children && <Tree data={d.children} />}
            </li>
          ))}
        </ul>
      );
      

    React 组件的种种用法,本质都是函数的用法。从函数的角度来理解、运用 React,就不会觉得这个框架很神秘了。