我仿造了一个掘金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 ,这些可以留给各位大佬自己去实现。

相关推荐
陈随易11 分钟前
AI新技术VideoTutor,幼儿园操作难度,一句话生成讲解视频
前端·后端·程序员
Pedantic14 分钟前
SwiftUI 按钮Button:完整教程
前端
前端拿破轮16 分钟前
2025年了,你还不知道怎么在vscode中直接调试TypeScript文件?
前端·typescript·visual studio code
代码的余温18 分钟前
DOM元素添加技巧全解析
前端
JSON_L21 分钟前
Vue 电影导航组件
前端·javascript·vue.js
用户214118326360229 分钟前
01-开源版COZE-字节 Coze Studio 重磅开源!保姆级本地安装教程,手把手带你体验
前端
大模型真好玩43 分钟前
深入浅出LangChain AI Agent智能体开发教程(四)—LangChain记忆存储与多轮对话机器人搭建
前端·人工智能·python
帅夫帅夫1 小时前
深入理解 JWT:结构、原理与安全隐患全解析
前端
Struggler2811 小时前
google插件开发:如何开启特定标签页的sidePanel
前端
爱编程的喵1 小时前
深入理解JSX:从语法糖到React的魔法转换
前端·react.js