基于React搭建个人空间

  • 开始
    • 注意
    • 原理
    • 涉及知识点
  • 项目
    • 项目结构
      • 描述
    • 源码
      • Login
      • Home
      • Header
      • Asider
      • Message
      • Photo
      • 其它文件
  • 运行项目
  • 效果图

开始

注意

项目需要手动安装axios和配置antd按需引入(可参考官方文档:https://3x.ant.design/docs/react/use-with-create-react-app-cn)。其实,不用配置也行,但每次需要import 'antd/dist/antd.css

原理

原理:

  • 项目基于React实现,通过axios发送请求获取数据,并通过bootstrap和antd进行页面渲染

涉及知识点

  • 掌握html,css,js三剑客基础知识以及弹性布局
  • 具备一定node.js基础,知道npm启动服务器就行
  • 具备一定的axios获取数据原理
  • 具备React基础知识,路由以及使用antd组件库

项目

项目结构

描述

Login(登录页)
Homer(主页)
Header(主页表头卡片)
Asider(侧边栏导航区)
Messa(个人信息展示)
Photo(接口加载的照片)
image(静态文件)

源码

注意:

  • 组件下每一个文件都包含在一个文件夹里,如Login/Login.jsx,Login/Login.css,下面不再声明!!!

Login

import React, { Component } from 'react'import './Login.css'
export default class Login extends Component {Login = () => {const { user, passwd } = thisif (user.value !== 'Admin' && passwd.value !== '123') return alert('用户或密码错误')localStorage.setItem('token', 'Bearer xxxx')//设置token验证 this.props.history.replace('/home')}render() {return (<div className="main"><div className="login-box"><div className="owl" id="owl"><div className="hand"></div><div className="hand hand-r"></div><div className="arms"><div className="arm"></div><div className="arm arm-r"></div></div></div><div className="input-box"><input ref={(c) => (this.user = c)} type="text" placeholder="账号" /><input ref={(c) => (this.passwd = c)} type="password" placeholder="密码" id="password" /><button onClick={() => this.Login()}>登录</button></div></div></div>)}
}
* {/* 初始化 */margin: 0;padding: 0;
}
.main {/* 100%窗口高度 */height: 100vh;/* 弹性布局 居中 */display: flex;justify-content: center;align-items: center;/* 渐变背景 */background: linear-gradient(200deg, #72afd3, #96fbc4);
}
.login-box {/* 相对定位 */position: relative;width: 320px;
}
.input-box {/* 弹性布局 垂直排列 */display: flex;flex-direction: column;
}
.input-box input {height: 40px;border-radius: 3px;/* 缩进15像素 */text-indent: 15px;outline: none;border: none;margin-bottom: 15px;
}
.input-box input:focus {outline: 1px solid lightseagreen;
}
.input-box button {border: none;height: 45px;background-color: lightseagreen;color: #fff;border-radius: 3px;cursor: pointer;
}
/* 接下来是猫头鹰的样式 */
.owl {width: 211px;height: 108px;/* 背景图片 */background: url('/src/image/owl-login.png') no-repeat;/* 绝对定位 */position: absolute;top: -100px;/* 水平居中 */left: 50%;transform: translateX(-50%);
}
.owl .hand {width: 34px;height: 34px;border-radius: 40px;background-color: #472d20;/* 绝对定位 */position: absolute;left: 12px;bottom: -8px;/* 沿Y轴缩放0.6倍(压扁) */transform: scaleY(0.6);/* 动画过渡 */transition: 0.3s ease-out;
}
.owl .hand.hand-r {left: 170px;
}
.owl.password .hand {transform: translateX(42px) translateY(-15px) scale(0.7);
}
.owl.password .hand.hand-r {transform: translateX(-42px) translateY(-15px) scale(0.7);
}
.owl .arms {position: absolute;top: 58px;width: 100%;height: 41px;overflow: hidden;
}
.owl .arms .arm {width: 40px;height: 65px;position: absolute;left: 20px;top: 40px;background: url('/src/image/owl-login-arm.png') no-repeat;transform: rotate(-20deg);transition: 0.3s ease-out;
}
.owl .arms .arm.arm-r {transform: rotate(20deg) scaleX(-1);left: 158px;
}
.owl.password .arms .arm {transform: translateY(-40px) translateX(40px);
}
.owl.password .arms .arm.arm-r {transform: translateY(-40px) translateX(-40px) scaleX(-1);
}

Home

import Header from '../Header/Header'
import React, { Component } from 'react'
import Asider from '../Asider/Asider'
import './Home.css'
export default class Home extends Component {render() {return (<div className="container"><Header /><Asider /></div>)}
}
body {background-color: #96fbc4;
}

Header

import React, { Component } from 'react'
import { PageHeader, Descriptions } from 'antd'
import './Header.css'
export default class Header extends Component {render() {return (<div className="site-page-header-ghost-wrapper"><PageHeader ghost={false} onBack={() => window.history.back()} title="React" subTitle="I love React!"><Descriptions size="small" column={3}><Descriptions.Item label="Created">李现</Descriptions.Item><Descriptions.Item label="Identity"><a href="https://github.com">student</a></Descriptions.Item><Descriptions.Item label="Creation Time">2022/3/23</Descriptions.Item><Descriptions.Item label="Effective Time">2022/3/23</Descriptions.Item><Descriptions.Item label="Remarks">Gonghu Road, Xihu District, Hangzhou, Zhejiang, China</Descriptions.Item></Descriptions></PageHeader></div>)}
}
.site-page-header-ghost-wrapper {padding: 24px;background-color: #2496d8;
}

Asider

import React, { Component } from 'react'
import { Menu } from 'antd'
import { AppstoreOutlined, PieChartOutlined, DesktopOutlined, ContainerOutlined, MailOutlined } from '@ant-design/icons'
import { Link, Route, Redirect } from 'react-router-dom'
import Message from '../Message/Message'
import Photo from '../Photo/Photo'
import './Asider.css'
// import 'antd/dist/antd.css'
const { SubMenu } = Menu
export default class Asider extends Component {state = {collapsed: false}//退出登陆close = () => {localStorage.removeItem('token')//清除token}toggleCollapsed = () => {this.setState({collapsed: !this.state.collapsed})}render() {return (<div className="mytbody">{/* 导航区 */}<div style={{ width: 256 }}><Menu defaultSelectedKeys={['1']} defaultOpenKeys={['sub1']} mode="inline" theme="dark" inlineCollapsed={this.state.collapsed}><Menu.Item key="1" icon={<PieChartOutlined />}><Link to="/home/message">个人资料介绍</Link></Menu.Item><Menu.Item key="2" icon={<DesktopOutlined />}><Link to="/home/photo">相册</Link></Menu.Item><Menu.Item key="3" icon={<ContainerOutlined />}><Link to="/" onClick={this.close}>退出</Link></Menu.Item><SubMenu key="sub1" icon={<MailOutlined />} title="Navigation One"><Menu.Item key="5">Option 5</Menu.Item><Menu.Item key="6">Option 6</Menu.Item><Menu.Item key="7">Option 7</Menu.Item><Menu.Item key="8">Option 8</Menu.Item></SubMenu><SubMenu key="sub2" icon={<AppstoreOutlined />} title="Navigation Two"><Menu.Item key="9">Option 9</Menu.Item><Menu.Item key="10">Option 10</Menu.Item><SubMenu key="sub3" title="Submenu"><Menu.Item key="11">Option 11</Menu.Item><Menu.Item key="12">Option 12</Menu.Item></SubMenu></SubMenu></Menu></div>{/* 展示区 */}<Route path="/home/message" component={Message} /><Route path="/home/photo" component={Photo} /><Redirect to="/home/message" /></div>)}
}
.mytbody {display: flex;
}

Message

import React, { Component } from 'react'
import { Layout } from 'antd'
import './Message.css'
// import img1 from '../../image/lx.jpg'
import img2 from '../../image/lx1.jpg'
import img3 from '../../image/lx2.jpg'
import img4 from '../../image/lx3.jpg'
const { Header, Footer, Sider, Content } = Layout
export default class Message extends Component {render() {return (<div><Layout><Sider><div className="profile">{/* eslint-disable-next-line jsx-a11y/alt-text */}<img src="http://pic1.win4000.com/wallpaper/2019-07-30/5d3ffcd996d7a.jpg" /><h3>李现</h3><p>actor</p><div className="share">{/* eslint-disable-next-line jsx-a11y/anchor-has-content */}<a href="https://www.baidu.com" className="fab fa-facebook-f"></a>{/* eslint-disable-next-line jsx-a11y/anchor-has-content */}<a href="https://www.baidu.com" className="fab fa-twitter"></a>{/* eslint-disable-next-line jsx-a11y/anchor-has-content */}<a href="https://www.baidu.com" className="fab fa-instagram"></a>{/* eslint-disable-next-line jsx-a11y/anchor-has-content */}<a href="https://www.baidu.com" className="fab fa-linkedin"></a></div><div className="buttons"><a href="https://www.baidu.com" className="btn">download cv</a><a href="https://www.baidu.com" className="btn">hire me</a></div></div></Sider><Layout><Header className="header-title"><h3 className="title">你不知道的李现</h3></Header><Content><div className="about"><p>李现,曾用名李晛,1991年10月19日出生于湖北省咸宁市,成长于湖北省荆州市 ,中国内地影视男演员,毕业于北京电影学院表演系2010级</p><p>李现出生于湖北省咸宁市,成长于湖北省荆州市,其父母在荆州市工作 [1] ,他在上初二的时候体重达到了160斤,到了高三时他的体重开始下降。李现高中就读于荆州中学,由于第一年高考不理想,第二年他便报考了表演和播音主持方向,之后顺利考上了北京电影学院表演系2010级 [23],而他也是当时湖北省荆州市第一位考取北京电影学院的大学生;此外,他还接受了电视台的采访,展示了吹萨克斯、弹吉他等才艺 [24] 。</p></div><div className="display"><ul><li>中文名:&nbsp;&nbsp;&nbsp;李现</li><li>&nbsp;名:&nbsp;&nbsp;&nbsp;李晛、现哥、现现</li><li>&nbsp;籍:&nbsp;&nbsp;&nbsp;中国</li><li>出生地:&nbsp;&nbsp;&nbsp;湖北省咸宁市</li></ul><ul><li>&nbsp;&nbsp;座:&nbsp;&nbsp;&nbsp;天秤座</li><li>&nbsp;&nbsp;高:&nbsp;&nbsp;&nbsp;185cm</li><li>&nbsp;&nbsp;业:&nbsp;&nbsp;&nbsp;演员</li><li>毕业院校:&nbsp;&nbsp;&nbsp;北京电影学院</li></ul></div></Content><Footer><div className="image"><h3 className="title">心之所"现"</h3><div className="box-container"><div className="box"><img src={img2} alt="" /></div><div className="box"><img src={img3} alt="" /></div><div className="box"><img src={img4} alt="" /></div></div></div></Footer></Layout></Layout></div>)}
}
:root {--blue: #2980b9;--black: #333;--white: #fff;--light-color: #777;--light-bg: #eee;--box-shadow: 0 5px 10px rgba(0, 0, 00, 0.1);
}* {font-family: serif;margin: 0;padding: 0;box-sizing: border-box;outline: none;border: none;text-decoration: none;text-transform: capitalize;transition: all 0.2s linear;list-style: none;
}.btn {margin-top: 10px;display: inline-block;padding: 7px 20px;border-radius: 5px;background: var(--blue);color: var(--white);font-size: 17px;
}.profile {flex: 1 1 400px;height: 600px;background: var(--white);padding: 30px 20px;text-align: center;position: sticky;border-right: 2px solid var(--black);top: 20px;left: 0px;
}.profile img {height: 150px;width: 150px;border-radius: 50%;border: 2px solid var(--black);object-fit: cover;margin-bottom: 10px;
}.profile h3 {color: var(--black);font-size: 20px;
}.profile p {color: var(--blue);padding: 5px 0;margin-bottom: 10px;font-size: 15px;
}.profile .share {margin: 10px 0;
}.profile .share a {height: 50px;width: 50px;line-height: 50px;font-size: 20px;border-radius: 50%;color: var(--black);background: var(--light-bg);
}.profile .share a:hover {background: var(--blue);color: var(--white);box-shadow: var(--box-shadow);
}
.title {margin-top: 10px;font-weight: 400;font-style: italic;letter-spacing: 1em;margin-bottom: 10px;padding-bottom: 5px;border-bottom: 1px solid #000;color: var(#fff);
}
.about p {color: var(--light-color);text-indent: 2em;line-height: 30px;
}
.display {display: flex;justify-content: space-around;
}.display ul {flex: 1 1 200px;padding: 10px 20px;font-size: 18px;font-weight: bold;
}.image .title {font-weight: 400;font-style: italic;letter-spacing: 1em;margin-bottom: 10px;padding-bottom: 5px;border-bottom: 1px solid #000;color: var(--blue);
}.image .box-container {display: flex;justify-content: space-around;
}
.image .box-container img {margin-right: 5px;width: 200px;height: 300px;
}
.header-title {background-color: #2496d8;
}

Photo

import React, { Component } from 'react'
import axios from 'axios'
// import { Button } from 'antd'
import './Photo.css'export default class Photo extends Component {state = {imgList: [],flag: false}componentDidMount() {axios.get('http://localhost:8080/api/photo').then((req) => {this.setState({imgList: req.data.data})},(err) => {console.log(err.message)})}componentWillUnmount() {this.setState = () => {return}}// getList = () => {//   axios.get('http://localhost:8080/api/photo').then(//     (req) => {//       this.setState({//         imgList: req.data.data//       })//     },//     (err) => {//       console.log(err.message)//     }//   )// }// hideList = () => {//   this.setState({//     imgList: []//   })// }render() {const { imgList } = this.statereturn (<div>{/* <Button type="primary" danger onClick={this.getList}>display</Button>&nbsp;&nbsp;<Button type="primary" danger onClick={this.hideList}>hide</Button> */}<div className="row">{imgList.map((item) => {return (<div className="col-sm-6 col-md-4" key={item.id}><div className="thumbnail"><img src={item.avator} alt="..." /><div className="caption"><h3>Thumbnail label</h3><p>...</p><p>{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}<a href="#" className="btn btn-primary" role="button">Button</a>{' '}{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}<a href="#" className="btn btn-default" role="button">Button</a></p></div></div></div>)})}</div></div>)}
}
.test {width: 400px;grid-template: 400px;
}

其它文件

index.html
引入样式

<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet" /><link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet" />

App.jsx

import React, { Component } from 'react'
import { Route, Redirect } from 'react-router-dom'import './App.css'
import Home from './components/Home/Home'
import Login from './components/Login/Login'export default class App extends Component {render() {return (<div>{/* exact精准匹配 */}<Route exact path="/" component={Login} /><Route path="/home" component={Home} /><Redirect to="/" /></div>)}
}

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'
import './index.css'
import App from './App'
import reportWebVitals from './reportWebVitals'ReactDOM.render(<BrowserRouter><App /></BrowserRouter>,document.getElementById('root')
)// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals()

接口文件
react_demo.js

const express = require('express')
const cors = require('cors')
const app = express()app.use(cors())app.use((req, res, next) => {console.log('请求中...')next()
})app.get('/api/photo', (req, res) => {const users = {msg: 'ok',status: 200,data: [{ id: 1, avator: 'http://pic1.win4000.com/wallpaper/2019-07-30/5d3ffcd996d7a.jpg' },{ id: 2, avator: 'http://pic1.win4000.com/wallpaper/2019-07-30/5d3ffcda5da91.jpg' },{ id: 3, avator: 'http://pic1.win4000.com/wallpaper/2019-07-30/5d3ffcdb1f5d2.jpg' },{ id: 4, avator: 'http://pic1.win4000.com/wallpaper/2019-07-30/5d3ffcdbd5403.jpg' },{ id: 5, avator: 'http://pic1.win4000.com/wallpaper/2019-07-30/5d3ffcdc9afb0.jpg' },{ id: 6, avator: 'http://pic1.win4000.com/wallpaper/2019-07-30/5d3ffcdd55abc.jpg' },{ id: 7, avator: 'http://pic1.win4000.com/wallpaper/2019-07-30/5d3ffcde159b8.jpg' },{ id: 8, avator: 'http://pic1.win4000.com/wallpaper/2019-07-30/5d3ffcded4110.jpg' },{ id: 9, avator: 'http://pic1.win4000.com/wallpaper/2019-08-02/5d44009e69276.jpg' }]}res.send(users)
})app.listen(8080, (err) => {// console.log(err)if (!err) {console.log('The server is running at http://localhost:8080/api/photo')}
})

运行项目

  1. nodemon .\react_demo.js 启动接口
  2. npm start 启动项目

效果图



react+node.js+antd+bootstrap实现个人空间案例

基于React搭建个人空间(更新版)相关推荐

  1. 基于React搭建一个美团WebApp

    一:React基础准备 1.1React是一个专注于View层的组件库,React提供设计的时候目标是尽可能的是接近原生,没有设计出很多高级的功能,这也为后来开发者自定义功能模块提供了很大的空间 1. ...

  2. 基于 React 搭建的 安卓,Ios,Web 三端架构(附上 IceE 三端框架)

    前言 本节介绍基于该架构的一个 CMS 项目,如果你没有兴趣了解,可以直接跳到下一节 本栏目的文章基于 IceEmblem 架构设计 Github:https://github.com/IceEmbl ...

  3. 基于React+Koa实现一个h5页面可视化编辑器-Dooring

    前言 前段时间笔者一直忙于数据可视化方面的工作,比如如何实现拖拽式生成可视化大屏,如何定制可视化图表交互和数据导入方案等,这块需求在B端企业中应用非常大,所以非常有探索价值. 本篇文章并非和数据可视化 ...

  4. 基于React Native的移动平台研发实践分享

    本文转自微信号EAWorld.扫描下方二维码,关注成功后,回复"普元方法+",将会获得热门课堂免费学习机会! 本文目录: 一.React Native 已经成为了移动前端技术的趋势 ...

  5. 空间句法软件_【特训营报名】空间句法理论与实践应用(第二期更新版)丨城市数据派...

    最新线上特训营  授课老师专业过硬负责空间句法官方中文网站建设作为主要译者翻译空间句法奠基作<空间的社会逻辑>此课程为空间句法初级课程的第二期更新版课程内容更丰富更完善教学视频永久观看 报 ...

  6. 从零搭建一个基于React+Nextjs的SSR网站(四):如何搭建服务器并部署Nextjs项目

    个人博客源码:https://github.com/shaotianyu/blog-front PS: 如果你有疑惑,可以给我留言,咱们一起解决它. 从零搭建一个基于React+Nextjs的SSR网 ...

  7. QQ空间游戏基地刷分0821更新版

    文档的名称是:QQ空间游戏基地刷分0821更新版 网址是:http://www.ucbug.com/qq/wg/20090816/807.html 游戏基地0821更新版 已经更新游戏到目前最新的 总 ...

  8. 从零开始搭建一套完整的基于 React 框架的 H5 项目「下载即用、收藏不亏」

    最近需要新开一个基于 React 移动端的项目.由于网上完整的 H5 初始化项目比较少,所以在此总结一下如何从 0-1 开发一套基于 React 框架的 H5 初始化项目,下载就可以直接进行开发,欢迎 ...

  9. 基于 react, redux 最佳实践构建的 2048

    前段时间 React license 的问题闹的沸沸扬扬,搞得 React 社区人心惶惶,好在最终 React 团队听取了社区意见把 license 换成了 MIT.不管 React license ...

最新文章

  1. python3.7.2怎么用不了pillow_python 3.7.0 下pillow安装方法
  2. 我的Android进阶之旅------gt;Java全角半角的转换方法
  3. 服务器信息采集协议,服务器信息采集
  4. react中使用create-react-app创建项目执行函数两次
  5. JAVA面向对象的特征
  6. java 异常_Java学习——异常与异常处理
  7. oracle包写入程序失败_Oracle内核技术揭秘第一篇
  8. 工业以太网交换机的作用和工作原理详解
  9. P1120-小木棍 [数据加强版]
  10. hibernate id生成策略 mysql_Hibernate中ID生成策略
  11. java三星题之_JAVA三星题之playing a TicTacToe game
  12. ceph:如何处理rados --striper上传失败的对象
  13. JDK 8.0 新特性——函数式接口和Lambda 表达式
  14. 发起成立“ABCD联盟”,人工智能与区块链技术研讨会北京站精彩回顾
  15. 黑苹果双系统访问其他磁盘windows/U盘或移动硬盘格式NTFS
  16. 运维(20) 制作启动U盘安装Win10
  17. 笔记:live2d4.0 sdk 博客园网页动画
  18. 刘备是怎样“融资”创业的?
  19. Spring 核心 之 AOP
  20. 大数据给交通行业带来的五大变革 | 交通数据的深度应用

热门文章

  1. 如何清洁你脏兮兮的笔记本电脑?
  2. linux下查看文件编码
  3. 移动机器人定位(amcl)
  4. Vue详解+实战分析
  5. Idea生成英文JavaDoc以及中文编码问题
  6. vultr 云主机收不到来自客户端的udp数据包
  7. ORA-600 Lookup Error Categories
  8. 联邦学习是什么?联邦学习简介
  9. 03Roberts算子
  10. TAElectronic-车辆电子电器模型库