• 如何支持组件的子元素任意摆放


    一个筛选组件如下图:

    filter bar component v1

    筛选组件包含一个 button 和一个 formbutton 能控制 form 的显示与隐藏。设计里 buttonform 在一行,实现时理所当然地把这一行封装成了一个组件。

    但在另一个项目里,设计有区别,button 被放到了面板的右上角,之前写的组件没法复用了。

    filter bar component v2


    看看之前封装的组件:

    function FilterBar() {
      const [showForm, setShowForm] = useState(true);
    
      return (
        <div className="container">
          <button
            onClick={() => setShowForm(pre => !pre)}
          >
            {showForm ? "<<< Filter" : "Filter >>>"}
          </button>
          {showForm && (
            <form>
              <label>
                Name <input />
              </label>
              <label>
                IP <input />
              </label>
            </form>
          )}
        </div>
      );
    }
    

    它做了以下 4 件事:

    1. 创建 button
    2. 创建 form
    3. 实现 buttonform 的联动,
    4. 创建容器 div.container, 对 buttonform 布局。

    「创建容器 div.container, 对 buttonform 布局」这件事导致了组件没法在新项目里复用。


    能不能写一个组件,不对子元素布局,把布局的工作交给组件使用者去做?

    思路:把 div.container 去掉,把 buttonform 的实例返回,组件变成了一个 hook。

    function useFilterBar() {
      const [showForm, setShowForm] = useState(true);
    
      return [
        <button
          onClick={() => setShowForm(pre => !pre)}
        >
          {showForm ? "<<< Filter" : "Filter >>>"}
        </button>,
        showForm ? (
          <form>
            <label>
              Name <input />
            </label>
            <label>
              IP <input />
            </label>
          </form>
        ) : (
          undefined
        )
      ];
    }
    
    function App() {
      const [filterBtn, filterForm] = useFilterBar();
    
      return (
        <div className="card">
          <Header title="Users">{filterBtn}</Header>
          {filterForm}
          <table>
            <thead>
              <tr>
                <th>Name</th>
                <th>IP</th>
              </tr>
            </thead>
            <tbody>...</tbody>
          </table>
        </div>
      );
    }
    

    class 组件没法用 hook 怎么办?

    思路:使用高阶组件,高阶组件是函数组件,可以使用 hook,然后把 buttonform 通过 props 传递给 class 组件。

    const withFilterBar = Cmp => props => {
      const [filterBtn, filterForm] = useFilterBar();
    
      return (
        <Cmp
          {...props}
          filterBtn={filterBtn}
          filterForm={filterForm}
        />
      );
    };
    

    我写这篇文章的目的不是为了记录技巧,而是希望对组件有新的思考:把「子元素关联关系 - 逻辑」和「子元素布局 - 视图」两件事拆开,让组件更灵活。

  • 相关阅读:
    添加可运行的js代码
    一,IL访问静态属性和字段
    UI基础UIWindow、UIView
    ASP.NET MVC:会导致锁定的会话
    2013腾讯编程马拉松初赛
    使用phantomjs生成网站快照
    C语言
    设置 Ext.data.Store 传参的请求方式
    HDU 2041 超级楼梯
    MySQL 监控-innotop
  • 原文地址:https://www.cnblogs.com/apolis/p/12611249.html
Copyright © 2020-2023  润新知