React+NodeJS打造个人博客(上)

1,127 阅读6分钟

前言

最近闲来无聊,公司项目总是一周工时硬是拉扯到一个月工时。 所以很是闲,想想公司项目都是用的vue框架开发,感觉自己一直没有用React开发一个完整项目,便想自己练练手。 既然说到练练手,刚好最近看了一下node.js。那就尝试两个结合一下吧,做个全栈项目玩玩。

如有写的不好还请评论区指出错误

请添加图片描述

一、前期准备

前端:React ,react-bootstrap,react-router6 后端:node 前端仓库地址:gitee.com/boyHuyou/re…

二、React篇(搭建静态页面)

1. 创建React项目

(1). 在E盘中创建项目blogs

不懂的可以看我另一篇关于创建React项目的教程blog.csdn.net/m0_52223449…

2. 启动React项目

(1). 项目创建成功后进入E盘下的blogs目录 (2). 打开终端运行npm start或yarn start (3). 在浏览器中输入http://localhost:3000/,端口若被占用,还请以实际输出地址为准

操作如下:

在这里插入图片描述


页面启动成功如下: 在这里插入图片描述

若以上操作看得云里雾里 ,还望再去学习React基础。当然如果创建项目插时出现问题或者安装create-react-app出现错误,应该是node版本或npm不对,具体以官网为准

3. 完成登录与注册页面

(1). 在src目录下创建Login文件夹和assets文件夹 (2). 在Login文件夹下创建index.jsx文件和index.css

大家可以根据自己开发习惯选择css预处理器,至于这里没有用到css预处理器,是因为担心安装过多依赖,会引起大家思路走散,所以会尽量减少不必要依赖

文件目录如下: 在这里插入图片描述

(3). 在index.css文件下放入初始化样式,样式如下

body,
div,
dl,
dt,
dd,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
h6,
pre,
code,
form,
fieldset,
legend,
input,
button,
textarea,
p,
blockquote,
th,
td {
  margin: 0;
  padding: 0;
}
body {
  background: #fff;
  color: #555;
  font-size: 14px;
}
td,
th,
caption {
  font-size: 14px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
  font-weight: normal;
  font-size: 100%;
}
address,
caption,
cite,
code,
dfn,
em,
strong,
th,
var {
  font-style: normal;
  font-weight: normal;
}
a {
  color: #555;
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}
img {
  border: none;
}
ol,
ul,
li {
  list-style: none;
}
input,
textarea,
select,
button {
  font: 14px;
}
table {
  border-collapse: collapse;
}
.clearfix:after {
  content: '.';
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}

(4). 安装react-bootstrap库,官网地址

  • 下载react-bootstrap
npm install react-bootstrap bootstrap
  • 引入样式 在index.js入口文件引入
import 'bootstrap/dist/css/bootstrap.min.css`
  • 使用组件 在需要的页面中引入Button,如图

在这里插入图片描述

(4). 在Login/index.jsx放入下列代码

因为自己React开发经验不是很成熟,毕竟之前一直在做vue开发,所以实现功能的逻辑可能比较low,还望见谅

import React, { Component } from 'react'
import { Form  , Button ,} from 'react-bootstrap';
import './index.css'
export default class index extends Component {
  state = {
      isLogin : true , // isLogin为true为登录页面,false为注册页面
      username : '',
      password : '',
      confirmpassword : ''
  }
  changeLogin = (type) => {
    this.setState({
     isLogin : type,
     username :'',
     password : '',
     confirmpassword : ''
    })
  }
  // 绑定表单值
  handleChange = (key, val) => {
    this.setState({
       [key]: val.target.value
    })
  }
 // 登录事件
  handleLogin = (e) => {
    e.preventDefault();
    console.log()
    const {username,password} = this.state
    console.log(username ,password ,'登录' )
  }
 // 注册事件
  handleRegister = (e) => {
    e.preventDefault();
    const {username,password,confirmpassword} = this.state
    console.log(username,password,confirmpassword ,'注册' )
  }
  render() {
    const {isLogin ,username,password,confirmpassword} = this.state
    if(isLogin){
    return (
      <div className='Login'>
        <div className='Login-main'>
        <Form>
          <Form.Group className="mb-3" >
            <Form.Label>用户名</Form.Label>
            <Form.Control type="test" placeholder="请输入用户名" value={username}  onChange={value => this.handleChange('username', value)} />
           
          </Form.Group>

          <Form.Group className="mb-3" >
            <Form.Label>密码</Form.Label>
            <Form.Control type="password" placeholder="请输入密码" value={password}  onChange={value => this.handleChange('password', value)}/>
          </Form.Group>
          <div className="d-grid gap-2">
            <Button variant="primary" type="submit" onClick = {this.handleLogin}>
              登录
            </Button>
            <Form.Text className="text-muted">
                还没有账号,前往<span className='a-link' onClick={() => this.changeLogin(false)}>注册</span> 
             </Form.Text>
          </div>
        </Form>
        </div>
      </div>
    )
    }else{
      return <div className='Login'>
      <div className='Login-main'>
      <Form>
        <Form.Group className="mb-3">
          <Form.Label>用户名</Form.Label>
          <Form.Control type="email" placeholder="请输入用户名"  value={username} onChange={value => this.handleChange('username', value)}/>
          <Form.Text className="text-muted">
            
          </Form.Text>
        </Form.Group>

        <Form.Group className="mb-3" >
          <Form.Label>密码</Form.Label>
          <Form.Control type="password" placeholder="请输入密码" value={password}  onChange={value => this.handleChange('password', value)}/>
        </Form.Group>
        <Form.Group className="mb-3" >
          <Form.Label>确认密码</Form.Label>
          <Form.Control type="password" placeholder="请确认密码" value={confirmpassword}   onChange={value => this.handleChange('confirmpassword', value)}/>
        </Form.Group>
        <div className="d-grid gap-2">
          <Button variant="primary" type="submit" onClick={this.handleRegister}>
            注册
          </Button>
          <Form.Text className="text-muted">
           前往 <span className='a-link' onClick={() => this.changeLogin(true)}>登录</span> 
           </Form.Text>
        </div>
      </Form>
      </div>
    </div>
    }
  }
}

(5). 在Login/index.css放入下列样式

这里有用到一张背景图,到时候需要的话可以去gitee仓库中下载

.Login {
  width: 100vw;
  height: 100vh;
  background: url('../../assets/loginBg.jpg') no-repeat;
  background-size: cover;
  display: flex;
  justify-content: center;
  align-items: center;
}
.Login-main {
  width: 450px;
  /* height: 450px; */
  background-color: rgba(0, 0, 0, 0.6);
  border-radius: 10px;
  padding: 46px;
}
.Login-main .d-grid {
  margin-top: 50px;
}
.Login-main .a-link {
  margin-left: 10px;
}
.Login-main .a-link:hover {
  cursor: pointer;
  color: #0d6efd;
}

(5). 最终完成效果如图 在这里插入图片描述

4. 完成整体布局

除了登录,这里差不多如下五个页面,看到这里是不是想起路由啦,是的!接下来我们进行一个简单路由分析,首先分为左右两部分,然后接下来进行页面拆减,这里对于页面静态代码的话可能就不会去讲解,需要的话可以去看我的一个源码

在这里插入图片描述

1. 安装React-router

我这边默认安装的是v6.4.4版本,使用6版本以下的不适合接下来的编程

npm install react-router-dom

2. 搭建页面

(1). 在pages文件夹建五个页面,分别是:整体布局——Home/index.tsx,首页——Article/index.tsx,写文章——Post/index.tsx,关于——Me/index.tsx,错误页面——Error/index.tsx

(2). 在src文件夹中新建router/index.js,在index.js中引入react和router相关配置,具体代码如下

import React, { lazy } from 'react'
import { Navigate } from 'react-router-dom'
import Home from '../pages/Home'
const Article = lazy(() => import('../pages/Article'))
const Post = lazy(() => import('../pages/Post'))
const Login = lazy(() => import('../pages/Login'))
const Me = lazy(() => import('../pages/Me'))
const Error = lazy(() => import('../pages/Error'))
// 用到lazy必须外面包一层  React.Suspense
const LazyLoad = (Comp) => (
  <React.Suspense fallback={<div> 加载中...</div>}>{Comp}</React.Suspense>
)

const routers = [
  {
    path: '/',
    element: <Navigate to="/article" />
  },
  {
    path: '/',
    element: <Home />,
    children: [
      { path: '/article', element: LazyLoad(<Article />) },
      { path: '/post', element: LazyLoad(<Post />) },
      { path: '/me', element: LazyLoad(<Me />) }
    ]
  },
  {
    path: '/login',
    element: <Login />
  },
  {a
    path: '*',
    element: <Error />
  }
]

export default routers

(3). 在App.js文件中引入我们写好的router并暴露出去,代码如下

import { useRoutes } from 'react-router-dom'
import routers from './router'
const App = () => {
  const routes = useRoutes(routers)
  return routes
}

export default App

(4). 一个简单的路由跳转就完成啦,接下来看看我们的成果 在这里插入图片描述

5. 封装路由守卫

因为个人博客是私密信息,所以当我们访问信息时应该先登录才能访问。否则的不能进入首页,应当拦截并强制进入登录页,和管理系统一个性质差不多。相信了解Vue的小伙伴们都知道,在Vue中我们如果需要操作路由拦截的话,Vue有自带的beforeEach。所以接下来我们在React中进行一个beforeEach的封装

我们来进行简单的一个思路分析,范围以下两种情况(token用为辨别以后是否登录) (1). 如果存在token并路径为登录时,应该跳转首页页 (2). 如果不存在token并路径不为登录时,应该跳转登录页 (3). 其它情况正常放行

(1). 有了上面的思路,接下来进行代码操作,在route文件夹新建BeforeRouteEnter.jsx文件,放以下代码

import { useEffect } from 'react'
import { useRoutes, useLocation, useNavigate } from 'react-router-dom'
import routers from './index'

//去往登录页的组件
function ToLogin() {
  const navigateTo = useNavigate()
  // 加载完这个组件之后实现跳转
  useEffect(() => {
    // 加载完组件之后执行这里的代码
    navigateTo('/login')
  }, [])
  return <div></div>
}

//去往首页的组件
function ToHome() {
  const navigateTo = useNavigate()
  // 加载完这个组件之后实现跳转
  useEffect(() => {
    // 加载完组件之后执行这里的代码
    navigateTo('/')
  }, [])
  return <div></div>
}


// 实现路由守卫
const BeforeRouteEnter = () => {
  const routes = useRoutes(routers)
  const token = true
  const location = useLocation()
  const navigateTo = useNavigate()
  const pathname = location.pathname
  console.log(location, 'routes')
  // 如果存在token并路径为登录时,应该跳转首页
  if (token && pathname === '/login') {
    // 如果这里直接通过navigateTo('/')跳转,会有当前一个页面的渲染,具体的可以了解一下React生命周期
    return <ToHome />
  }
  // 如果不存在token并路径不为登录时,应该登录`在这里插入代码片`
  if (!token && pathname !== '/login') {
    return <ToLogin />
  }
  // 其他情况放行
  return routes

}


export default BeforeRouteEnter

(2). 将App.js文件的内容修改如下

import BeforeRouteEnter from './router/BeforeRouteEnter'
const App = () => {
  return <BeforeRouteEnter />
}

export default App

总结

以上就是今天要讲的内容,本文仅仅讲解《React+NodeJS打造个人博客》静态页面的搭建,关于NodeJS将作为下一篇来讲解。由于这是第一次用React从零搭建,还有使用的React-bootstrap也是第一次用,如有写的不好的地方还望多多指教