现在有个场景,列表页展示的文章和详情页展示的文章没有太大差异,比如列表页不显示正文,而详情页显示全部,两个页面展示的时间位置需要稍微调整。
列表页布局
详情页布局
可以看到列表页不需要显示正文,同时时间的位置需要调整,如果把整体作为一个组件,应对这种布局上 有差异的场景,调整起来就不太方便。
解决方法:可以使用useContext作为管理状态的根组件,标题、时间、描述、图片、正文等分别 作为一个子组件,而不是在一个组件写死,这样可以根据需要很灵活地调整布局。
创建一个context管理数据,子组件使用useContext使用数据,为了子组件使用方便,把context在一个函数内导出,同时限制子组件必须在根组件Root内,否则抛出错误。
import { createContext, useContext } from "react";
const ArticleContext = createContext(null);
function useArticleContext() {
const context = useContext(ArticleContext);
if (!context) {
throw new Error("子组件必须位于Root根组件内!");
}
return context;
}
export { ArticleContext, useArticleContext };
根组件
根组件中传入供子组件使用的数据
<ArticleContext.Provider value={article}>
{children}
</ArticleContext.Provider>
标题组件
export default function Title() {
const { title } = useArticleContext();
return (
<div className={styles.title}>
<div>{title}</div>
</div>
);
}
时间组件
export default function Time() {
const { createdTime } = useArticleContext();
return <div className={styles.time}>{createdTime}</div>;
}
为了方便管理可以在一个文件统一导出根组件及子组件
import Root from "./Root";
import Time from "./Time";
import Title from "./Title";
const components = {
Root,
Title,
Time,
...
};
export default components;
然后在需要的地方使用
列表页:标题和时间在同一行显示。
<Components.Root article={article}>
<div className={styles.header}>
<Components.Title></Components.Title>
<Components.Time></Components.Time>
</div>
</Components.Root>
详情页:标题和时间在不同行显示。
<Components.Root article={article}>
<Components.Title></Components.Title>
<Components.Time></Components.Time>
</Components.Root>
可以看到使用起来很方便,可以随意排列这些子组件达到不同布局的目的,而一旦子组件在Root根组件外面使用,就会报错。