一个筛选组件如下图:
筛选组件包含一个 button
和一个 form
,button
能控制 form
的显示与隐藏。设计里 button
和 form
在一行,实现时理所当然地把这一行封装成了一个组件。
但在另一个项目里,设计有区别,button
被放到了面板的右上角,之前写的组件没法复用了。
看看之前封装的组件:
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 件事:
button
,form
,button
和 form
的联动,div.container
, 对 button
和 form
布局。「创建容器 div.container
, 对 button
和 form
布局」这件事导致了组件没法在新项目里复用。
能不能写一个组件,不对子元素布局,把布局的工作交给组件使用者去做?
思路是:把 div.container
去掉,把 button
和 form
的实例返回,组件变成了一个 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,然后把 button
和 form
通过 props
传递给 class 组件。
const withfilterbar = cmp => props => { const [filterbtn, filterform] = usefilterbar(); return ( <cmp {...props} filterbtn={filterbtn} filterform={filterform} /> ); };
我写这篇文章的目的不是为了记录技巧,而是希望对组件有新的思考:把「子元素关联关系 - 逻辑」和「子元素布局 - 视图」两件事拆开,让组件更灵活。
如对本文有疑问, 点击进行留言回复!!
selenium + ajax抓取英雄联盟全部英雄的详细信息及多线程保存全部皮肤图片到本地
网友评论