React实战篇(仿ONE·一个)

224 阅读4分钟

前言

根据自己所学的技术,整合起来模仿一个网站的页面。

所要仿的页面网站:ONE·一个

所用到的技术

开始

准备一个项目:npx create-react-app mproject-one

安装上述中除React以外的全部技术 npm i xxx(名字即可) -save

项目结构

image.png

  • src
    assets: 静态资源文件,存放图片啥的
    components: 常用组件
    mock:数据模拟
    page:路由组件
    route: 路由管理
    ...

项目页面分析

拆分组件:

  • 整体页面

image.png

  • 内容部分

image.png

分析并且拆解完组件之后,紧接着就是对每一模块的组件的代码编写

数据的模拟和获取

当页面编写完成,需要有数据显示才能更好的来调整页面的样式,因此这里我选择使用mock+axios来模拟数据和获取数据

模拟数据

新建一个mock文件夹,以及在该文件夹中新建一个index.js文件

import Mock, { Random } from 'mockjs'

//获取文章的数据
Mock.mock('api/articles', 'get', () => {
  return {
    status: 200,
    message: '获取文章成功',
    list: Mock.mock({
      'articlesList|7': [
        {
          "id|+1": 1,
          "title": '@ctitle(5, 15)',
          "content": '@cparagraph(500,1000)',
          "time": '@date()',
          "brief": "@csentence(10,15)",
          "author": '@cname()',
          "principal": '@name()',
          "img_url": Random.image('566x377', '#50B347', '#FFF', ' Hello')
        }
      ]
    }),
  }
})

//获取问题的数据
Mock.mock('api/problems', 'get', () => {
  return {
    status: 200,
    message: '获取问题成功',
    list: Mock.mock({
      'problemsList|7': [
        {
          "id|+1": 1,
          "problem": '@ctitle(5, 15)',
          "principal": '@name()',
          "answerList|10-20": [
            {
              "aid|+1": 1,
              "content": '@cparagraph()',
              "name": '@cname()',
            }
          ],
        }
      ]
    }),
  }
})

再在入口文件index.js中引入上面的mock文件,即:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

//引入mock文件
import "./mock/index"


ReactDOM.render(
    <App />
  , document.getElementById("root"));

获取数据

在文章组件中引入axios,在通过mock的url来获取数据

import React, { useEffect, useState } from "react";
import "./index.css";
import axios from "axios";
import Content from "../../../component/Content";

export default function Articles() {
  const [articlesList, setArticlesList] = useState([]);

//组件第一次渲染时获取数据
  useEffect(() => {
    axios.get("api/articles").then((res) => {
      setArticlesList(res.data.list.articlesList);
    });
  }, []);

//此处为后续的组件封装
  return <Content title="ONE 文章" dataList={articlesList} />;
}

image.png

公共组件提取

可以看出文章和问题两个组件样子很相似,此时我们就可以将它们提取出来形成一个公共组件,再分别在相对应的组件中传递数据给这个公共组件即可。

公共组件:

import React from "react";
import { Link } from "react-router-dom";

export default function Contents(props) {

//需要传递标题名和数据
  const { title, dataList } = props;
  return (
    <>
        <div className="articles">
          <h4 className="title">{title}</h4>
          <div>
            {dataList.map((item, index) =>
              index === 0 ? (
                <div className="firstArticle" key={item.id}>
                  <p className="firstArticle_id">VOL.{item.id}</p>
                  <p className="firstArticle_title">
                    <Link to={`/problem/${item.id}`} state={{ item }}>
                      {item.problem}
                    </Link>
                  </p>
                </div>
              ) : (
                <li key={item.id}>
                  <span>VOL.{item.id}</span>
                  <Link to={`/problem/${item.id}`} state={{ item }}>
                    {" "}
                    {item.problem}
                  </Link>
                </li>
              )
            )}
          </div>
        </div>
    </>
  );
}

文章组件:

//导入公共组件
import Contents from "../../../component/Contents";

//将所需要的数据传给公共组件
<Contents title="ONE 文章" dataList={articlesList} />

问题组件也是如此

路由方面

现在直接安装react-router-dom是6.x版本,在这个版本上更改了一些API也增加了一些API,详情请看我之前写的博客React---路由

分析

  1. 点击页面跳转之后该在何处显示?

  2. 需要编写路由有哪些?

  3. 是否存在子级路由?

根据分析的这些,可以得出结论:

  • 点击跳转之后页面是显示在内容部分的,头部和尾部不需要动

  • 路由都只是一级路由,可根据原页面的跳转链接来编写路由

代码编写

  • 创建route文件夹并且在该文件夹中创建index.js文件,来编写路由表
//引入匹配的路径之后需要跳转显示的组件
import Middle from '../page/Middle'
import ArticleDetail from '../page/Details/Article'
import ProblemDetail from '../page/Details/Problem'
import PictureDetail from '../page/Details/Picture'
import Acercade from '../page/Acercade'
import { Navigate } from 'react-router-dom'
import Politica from '../page/Politica'
import Contacto from '../page/Contacto'

const routes = [
  {
    path: '/',
    element: <Middle />
  },
  {
    path: '/article/:id',
    element: <ArticleDetail />
  },
  {
    path: '/problem/:id',
    element: <ProblemDetail />
  },
  {
    path: '/one/:id',
    element: <PictureDetail />
  },
  {
    path: '/acercade',
    element: <Acercade />
  },
  {
    path: '/politica',
    element: <Politica />
  },
  {
    path: '/contacto',
    element: <Contacto />
  },
  {
    path: '/',
    element: <Navigate to="/" />
  }
]

export default routes
  • 在APP.jsx中使用useRoutes来根据路由表,来动态创建<Routes><Route>
import React from "react";
import Head from "./page/Head";
import Foot from "./page/Foot";
import "./App.css";
import { useRoutes } from "react-router-dom";
import routes from "./route";

import { Layout } from "antd";

const { Header, Footer, Content } = Layout;

export default function App() {
  const element = useRoutes(routes);
  return (
    <>
      <Layout>
        <Header>
          <Head />
        </Header>
        <Content>{element}</Content>
        <Footer>
          <Foot />
        </Footer>
      </Layout>
    </>
  );
}
  • 最后再将代码中的a标签换为Link标签,并且将href换为to以及其对应的路径

代码地址

GitHub-仿ONE “一个”页面代码