我仿造了一个掘金App的首页...

前言

大家好,最近作者在做项目,中途发现前段时间学习的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 />&nbsp;{item.lookNum}</li>
                                <li><LikeO />&nbsp;{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 ,这些可以留给各位大佬自己去实现。

相关推荐
AlienZHOU4 小时前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
Captaincc7 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师8 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen9 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒9 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow9 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林8189 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang800789 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明9 小时前
第 6 章 组件进阶
前端·vue.js
江华森9 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端