highlight: agate theme: channing-cyan
「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战」
源码地址: https://gitee.com/yang-yiming1234/umi_blog
我们之前的文章已经实现了用markdown创建文章并且存入数据库中。如果想看之前的发布markdown的几篇文章,请看我的专栏 模仿掘金做个博客。
那么这篇文章我们对存入数据库中的文章进行一个展示。我们这篇文章先实现一下如下的一个首页。
先说一下布局,我们就按照布局讲解:
<div className={style.container}>
<div className={style.top}>
<div className={style.top_left}>
Tabs
</div>
<div className={style.top_center}>
搜索框
</div>
<div className={style.top_right}>
<div className={style.avator_con}>
头像
</div>
<div className={style.author}>
用户姓名标签
</div>
</div>
</div>
<div className={style.middle}>
<div className={style.nav}>
左侧导航
</div>
<div className={style.content}>
文章简介展示
</div>
<div className={style.mine}>
<Calender />
<div className={style.mine_bottom}>
<Weather />
</div>
</div>
</div>
</div>
这里最好下载一下源码,然后对照着看。
// 引入 Tabs组件
import { Tabs } from 'antd';
// 解构出 TabPane
const { TabPane } = Tabs;
// 文章类型 Tabs用的数据
const [articleType, setArticleType] = useState([]);
// 查询文章接口 tabs和搜索框共用
const searchAuthorOrTitle = (search=searchParams) => {
getArticle(search).then(res => {
const { data } = res;
setArticles(data);
});
};
// 在useEffect中请求接口 也就是页面加载就请求
useEffect(() => {
// 请求文章类型接口
getArticleType({}).then(res => {
// 这个数据作为Tabs的“全部”选项 传空参数
let temp = [{ id: 0, type: '' }];
// 将{ id: 0, type: '' }和接口数据合并
temp = [...temp, ...res.data];
// 赋值给articleType
setArticleType(temp);
});
}, []);
<div className={style.top_left}>
<Tabs
// 正常来说 key最好别用中文,我这里为了方便key都是中文。
// defaultActiveKey 默认选中的key
defaultActiveKey={'全部'}
// 选择其他Tab
onChange={key => {
//改变查询参数
setSearchParams({ ...searchParams, type: key });
// 调用查询文章接口
searchAuthorOrTitle({ ...searchParams, type: key });
}}
>
{/* 渲染Tabs */}
{articleType.map((item, index) => (
// 如果type的值是空 展示 '全部'
<TabPane tab={item.type === '' ? '全部' : item.type} key={item.type} />
))}
</Tabs>
对应样式
.top {
width: 100%;
height: 70px;
text-align: center;
padding: 10px;
display: flex;
// 固定
position: fixed;
z-index: 9;
background-color: #eff0f4;
.top_left {
flex: 1;
padding-left: 20px;
padding-right: 20px;
}
}
SearchOutlined
import { Col, Row, Input, Button, Tabs, Tag, Avatar } from 'antd';
import { SearchOutlined, GithubOutlined, CalendarOutlined } from '@ant-design/icons';
<div className={style.top_center}>
<Input
placeholder="搜索🔍题目、作者"
style={{ borderRadius: '20px', width: '100%' }}
// 改查询参数
onChange={e => {
setSearchParams({
title: e.target.value,
username: e.target.value,
});
}}
suffix={(
// 点击按钮调用查询接口也就是跟刚才Tabs一样的接口
<Button
type="primary"
shape="circle"
icon={<SearchOutlined />}
onClick={() => {
searchAuthorOrTitle();
}}
/>
)}
/>
</div>
样式
只是控制 搜索框的位置 和长度
.top_center {
flex: 1;
}
如果不使用Avatar组件,我们用img去渲染头像的话。会失真、形状改变。
Tag 组件 传入 color参数来改变颜色
import { Col, Row, Input, Button, Tabs, Tag, Avatar } from 'antd';
<div className={style.top_right}>
<div className={style.avator_con}>
<Avatar
className={style.avator}
src="https://gw.alipayobjects.com/zos/antfincdn/LlvErxo8H9/photo-1503185912284-5271ff81b9a8.webp"
/>
</div>
<div className={style.author}>
<Tag color="#108ee9">{userInfo.username}</Tag>
</div>
</div>
.top_right {
flex: 1;
padding-right: 10px;
display: flex;
justify-content: right;
.avator_con {
width: 50px;
height: 50px;
border-radius: 50%;
margin-right: 5px;
.avator {
width: 50px;
height: 50px;
border-radius: 50%;
}
}
.author {
line-height: 50px;
font-weight: 600;
}
}