前言
大家好,最近作者在做项目,中途发现前段时间学习的CSS,特别是弹性布局等内容,已经有点遗忘了, 于是作者准备再温习一下这些知识,并且应用一下,于是作者就有个想法:学习一下掘金APP的源码,并且试着自己动手仿造一下首页
由于是需要复习CSS的动手能力,作者在完成的时候,基本上没有用AI,纯自己手敲CSS,所以很多地方的命名规范,以及页面效果可能不是特别完美,大佬们莫喷
最终效果

可以看到,很多地方是差强人意的,作者主要想复习一下布局类的知识,所以很多细节就没有实现了
制作过程
这个案例就模拟掘金APP的首页部分,其它部分没有进行制作,但是整个React的结构还是模拟了下的
一、配置路由&基本项目结构
首先是创建了一个React的项目,配置了一下路由啥的,算是完成项目的一个Demo版本
配置路由
main.jsx
js
import {
BrowserRouter as Router
} from 'react-router-dom'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<Router>
<App />
</Router>
)
App.jsx
js
import { useState } from 'react'
import {
Routes,
Route,
Navigate
} from 'react-router-dom'
import './App.css'
import MainLayout from './components/MainLayout'
import BlankLayout from './components/BlankLayout'
import Home from './pages/Home'
import Synthesis from './pages/Synthesis'
import List from './pages/List'
import Back from './pages/Back'
import Front from './pages/Front'
import Search from './pages/Search'
function App() {
return (
<>
<Routes >
<Route path='/' element={<MainLayout />}>
<Route path='/' element={<Navigate to='/home' />} />
<Route path='/home' element={<Home />} />
<Route path='/synthesis' element={<Synthesis />} />
<Route path='/list' element={<List />} />
<Route path='/back' element={<Back />} />
<Route path='/front' element={<Front />} />
</Route>
<Route path='/' element={<BlankLayout />}>
<Route path='/search' element={<Search />} />
</Route>
</Routes>
</>
)
}
export default App
注意:作者只是遵循一般的项目结构,设计路由以及一般的项目结构,由于作者是准备主要练习下CSS,所以就只会实现布局(./components/MainLayout)和首页(./pages/index.jsx)的页面设计,其它部分空壳,以后作者有空说不定会完善 整个掘金APP

大家可以看看我的项目的页面以及组件等结构,现在还是一副空壳,什么都没有,待会咱们要填充部分内容
这里作者还做了一步:在仿掘金/juejin/index.html
文件中,添加了user-scalable=no
这一步虽然很简单,但是却十分的重要!!!!
以后我们真正开发一个项目一定要注意添加user-scalable=no
它让使用户在使用手机设备时不用受拖拽的影响页面的缩放与挪动,是我们前端开发中适配移动端设备的十分重要的一环
如果你没有添加这个就上线了,那么你很大概率就会被用户喷的体无完肤,然后就被老板给炒了
当然为了适配移动端设备,还需要使用rem + lib-flexible + postcss-pxtorem
,这个比较麻烦,由于我是学习CSS,就不在项目中体现了,大家如果感兴趣,可以去看我的文章移动端适配方案:rem + lib-flexible + postcss-pxtorem 最佳实践
二、MainLayout实现
接下来让我们写一下页面的布局吧,这个项目有两个页面布局,一个是MainLayout,另一个是BlankLayout,另一个布局这里暂时不赘述其含义,感兴趣的朋友可以去看《提升用户体验的前端基石:深度解析Layout系统设计》这篇文章
在这个MainLayout,我们要完成的是这一部分:

源码如下:
/src/components/MainLayout/index.jsx
jsx
import {
useState
} from 'react'
import {
Outlet,
useNavigate
} from 'react-router-dom'
import { Image,Search } from 'react-vant';
import { Bell } from '@react-vant/icons';
const MainLayout = () =>{
const navigate = useNavigate();
const navList = [
{
id: 1,
title:'关注',
path: '/home',
},
{
id: 2,
title:'综合',
path: '/synthesis',
},
{
id: 3,
title:'排行榜',
path: '/list',
},
{
id: 4,
title:'后端',
path: '/back',
},
{
id: 5,
title:'前端',
path: '/front',
},
{
id: 6,
title:'Android',
path: '/1',
},
]
const [active,setActive] = useState(1);
return (
<div className='container'>
<div className="header">
<Image src='https://fxsh.com/wp-content/uploads/2023/12/540a8-juejin.cn.png' className='pic1'
width="35px" height="35px"
/>
<h2 className='title'>首页</h2>
<div className="search" ><Search placeholder="3Katrina"/></div>
<div className='bell'><Bell fontSize="30px"/> </div>
<div className="pic2"><Image src='https://d.musicapp.migu.cn/data/oss/resource/00/2s/td/a7ec0786330841ea9354ed3dbac084c3.webp' width="35px" height="35px" round/></div>
</div>
<div className="nav">
{
navList.map((nav) => (
<span
key={nav.id}
className={nav.id==active ? "span_isSelect" : ""}
onClick={() => {
navigate(nav.path)
setActive(nav.id)
}
}
>
{nav.title}
</span>
))
}
</div>
<Outlet />
</div>
)
}
export default MainLayout
这里的css如下,我是按顺序排放了每个元素的,大家可以自己对应
/src/App.css
css
.container {
background-color: rgb(242, 243, 245);
}
.header {
display: flex;
height: 60px;
padding: 5px;
background-color: #ffffff;
}
.pic1 {
padding: 10px;
}
.title {
margin-left: 5px;
font-size: 16px;
width: 36px;
line-height: 54px;
font-weight: normal;
color: #1e80ff;
}
.search{
width: 150px;
}
.bell {
margin-left: 30px;
margin-right: 15px;
line-height: 70px;
}
.pic2 {
padding: 10px;
}
.nav {
background-color: #F9F9FA;
height: 46px;
}
.nav span{
padding: 0 12px;
font-size: 14px;
font-weight: 500;
line-height: 45px;
color: #515767;
}
.nav span:first-child {
padding: 0 18px;
}
.nav .span_isSelect {
color: #1e80ff;
}
这个MainLayout开发完之后就可以实现SPA(单页应用布局)了,只不过其它模块的东西还没写,效果是下面的这样的:可以切换网页地址以及根据路由部分渲染
三、Home实现
接下来我们写这一部分

源码如下:
src/pages/Home/index.jsx
js
import './index.css'
import {
BrowsingHistoryO,
LikeO
} from '@react-vant/icons';
const Home = () => {
const articles = [
{
id:1,
title: 'React批处理机制深度解析...',
description: '大家好,我是3Katrina,今天要介绍的内容...',
author:'3Katrina',
time:'2小时前',
lookNum:6,
likeNum:3,
},
{
id: 2,
title: 'Vue3组合式API实战',
description: '详解Vue3组合式API使用...',
author: '码海游侠',
time: '1小时前',
lookNum: 12,
likeNum: 8,
},
{
id: 3,
title: 'Webpack优化指南',
description: '分享Webpack打包优化技巧...',
author: '前端老司机',
time: '3小时前',
lookNum: 24,
likeNum: 15,
},
{
id: 4,
title: 'TypeScript进阶',
description: 'TS高级类型系统解析...',
author: 'TS爱好者',
time: '5小时前',
lookNum: 18,
likeNum: 9,
},
{
id: 5,
title: 'Node.js性能调优',
description: 'Node服务性能优化方案...',
author: '后端小工',
time: '昨天',
lookNum: 32,
likeNum: 20,
},
{
id: 6,
title: 'CSS新特性解析',
description: '介绍CSS最新特性...',
author: '样式魔法师',
time: '2天前',
lookNum: 45,
likeNum: 28,
}
]
return (
<>
<div className="content">
{
articles.map((item) => (
<div className='article'>
<h3>{item.title}</h3>
<p>{item.description}</p>
<footer>
<li>{item.author}</li>
<li>{item.time}</li>
<li><BrowsingHistoryO /> {item.lookNum}</li>
<li><LikeO /> {item.likeNum}</li>
</footer>
</div>
))
}
</div>
</>
)
}
export default Home;
css如下,同样也是按照顺序写的:
./src/pages/Home/index.css
css
.content {
margin-top: 20px;
}
.article {
box-sizing: border-box;
padding: 12px 20px 0px;
height: 99px;
background-color: #ffffff;
border-bottom: 1px solid #f5f4f4;
}
h3 {
font-size: 16px;
font-weight: 550;
margin-bottom: 10px;
}
p {
font-size: 13px;
font-weight: 400;
color: #8A919F;
margin-bottom: 10px;
}
footer {
display: flex;
font-size: 13px;
color: #8A919F;
}
footer li {
padding: 0 12px;
list-style: none;
}
footer li:nth-child(1) {
padding-left: 0px;
padding-right: 12px;
border-right: 1px solid #E4E6EB;
}
footer li:nth-child(2){
border-right: 1px solid #E4E6EB;
}
总结
至此,这个首页的页面就设计完了,后续可以根据这个MainLayout设计导航栏中不同内容对应的页面,我的源码有很多地方是重复可以优化的,但是为了读者能够按照顺序去读css,就没有优化了,这个项目只是为了练习CSS,所以很多地方就没有那么注重性能啥的,包括咱们其实可以用原子CSS的特性去设计,CSS IN JSS ,这些可以留给各位大佬自己去实现。