React 练习项目,仿简书博客写作平台

Introduction

技术栈:react + redux + react-router + express + Nginx

练习点:

  • redux 连接
  • react-router 路由跳转
  • scss 样式书写
  • 容器组件与展示组件的设计
  • express 脚手架项目结构设计
  • 用户信息持久化(cookie + redis)
  • 常见安全问题处理(xss sql 注入 cookie 跨域)
  • Promise 封装数据库操作
  • PM2 进程守护

线上体验地址:点我跳转
github:https://github.com/ChenMingK/blog-proj 欢迎 star?

Show

Design

在这里插入图片描述

前端

项目结构

|-- src
  |-- api                 // 所有API请求(axios)
  |-- assets              // 字体图标、全局/混合样式
  |-- components          // 展示组件 / 作为某个页面的局部的组件
    |-- common            // 可复用的组件
    |-- home              // home 页面所用到的组件,即 home 页面由这些组件构成
    |-- edit              // edit 页面所用到的组件
  |-- pages               // 容器组件 / 该组件整体作为一个页面展示,与 redux 连接并将 store 中的数据传递给其子组件
    |-- login             // 登录页
    |-- home              // 首页
      |-- Home.jsx        // react 组件
      |-- Home.scss       // 该组件的样式文件 
      ......|-- store               // redux
    |-- home              // home 页对应的 store
      |-- action-type.js  // action 类型
      |-- actions.js      // action 构造器
      |-- index.js        // 用于整体导出
      |-- reducer.js      // 该 module 的 reducer
    |-- module2           // 这个文件夹只是为了说明如果有 redux 有新的 module 需要引入就和 home 文件夹下格式一样
    |-- store.js          // 合并 reducer,创建 store(全局唯一)并导出,如果需要应用中间件,在这里添加
|-- App.js                // 根组件 / 定制路由
|-- index.js              // 项目入口 / webpack 打包入口文件

react-router-dom 路由跳转的几种方式

1.引入<Link> 组件并使用,但是其有默认的样式(比如下划线),还要修改其默认样式

import <Link> from 'react-router-dom'
...
<Link to="/login" className="login-btn">
  <span className="login-text">登录</span>
</Link>

2.导入 withRouter 使用 js 方式跳转

import { withRouter } from 'react-router-dom'

// 需要对该组件做如下处理(这是与 redux 连接的同时又使用 withRouter 的情况)
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header))

// js 方法实现路由跳转
this.props.history.push('/')

// 简单来说就是通过某种方式(context?)把 history 给传递到这个组件了

回到顶部的过渡效果

1.利用 window.scrollTo(xpos, ypos) 方法加上 transition: all linear .2s 来实现 - 该方案无效

2.利用元素的 scrollTop 属性,点击回到顶部按钮时设置元素的 scrollTop: 0 再添加 transition 属性来实现 - 无法对 scrollTop 属性实现过渡

3.该元素的 css 中添加 scroll-behavior: smooth; 点击回到顶部按钮时设置元素的 scrollTop: 0 - OK

利用 <hr> 画分割线

hr {
  border-color: #eaeaea;
  border: 0; // 默认横线
  border-top: 1px solid #eee; // 画条灰色横线
  margin-left: 65px; // 这是块级元素,可以用 margin 来控制横线长度
  margin-right: 15px;
}

利用 transform:scaleX() 实现下划线伸缩效果

.menu-item {
  @include center;
  width: 100px;
  color: #969696;
  font-weight: 700;
  font-size: 16px;
  position: relative;
  .icon {
    margin-right: 5px;
  }
  // 利用伪元素给这个 item 加 "下划线"
  &:after {
    content: '';
    position: absolute;
    width: 100%;
    border-bottom: 2px solid #646464;
    top: 100%;
    transform: scaleX(0);
    transition: all linear .2s;
  }
  // hover 时改变 scaleX
  &:hover {
    color: #646464;
    cursor: pointer;
    &:after { // 咋选的?
      transform: scaleX(1);
    }
  }
}

利用 DOM 操作手动添加的事件处理程序要手动移除

// 假设在加载组件时这样添加事件处理程序
componentDidMount() {
   
  let app = document.getElementsByClassName('App')[0]
  app.addEventListener('scroll', this.handleScroll, false)
}

// 就需要这么移除,否则会报内存泄漏,另外注意这里的 this.handleScroll 必须是与上面的 addEventListener 相同的引用
componentWillUnmount() {
   
  let app = document.getElementsByClassName('App')[0]
  app.removeEventListener('scroll', this.handleScroll, false)
}

防止无意义的渲染

shouldComponentUpdate(nextProps, nextState) {
   
  // ArticleList 组件是从父组件拿到的 articlelist,发现在内容没变的情况下页面向下滚动就会触发 render 函数
  // 投机取巧......
  return nextProps.articleList.length !== this.props.articleList.length
}

自己实现一个带边框的 tooltip

在这里插入图片描述

小三角就用我们熟悉的 css 画三角来画,如果我们想给这个 tooltip 外层加一个边框?可以再利用一次伪元素来画一个三角形,其颜色
就是边框颜色,利用高度差来实现这个边框效果。

&:after {
  content: ''; // 记得加 content 才行
  width: 0;
  height: 0;
  border-width: 10px;
  border-style: solid;
  border-color: #fff transparent transparent transparent;
  position: absolute;
  top: 100%;
  left: 50%;
  z-index: 101;
  margin-left: -10px;
}
// 如果我想给小三角再加个边框?
&:before {
  content: '';
  width: 0;
  height: 0;
  border-width: 11px;
  border-style: solid;
  border-color: #f0f0f0 transparent transparent transparent;
  position: absolute;
  top: calc(100% + 1px); // calc 大法好
  left: 50%;
  z-index: 100;
  margin-left: -11px;
}

后端

项目结构

|--bin
  |-- www                 // 入口文件 / 启动文件
|-- conf                  // 配置项
  |-- db.js               // 数据库连接配置 / redis 连接配置
|-- controller
  |-- blog.js             // 处理 blog 路由相关逻辑(将逻辑操作封装为函数并导出由供路由处理部分使用)
  |-- user.js             // 处理 user 路由相关逻辑
|-- db
  |-- mysql.js            // 建立 mysql 连接,将执行 sql 操作封装为 Promise 并导出
  |-- redis.js            // 建立 redis 连接,封装 set、get 操作并导出
|-- middleware
  |-- loginCheck.js       // 自定义的中间件
|-- model
  |-- resModel.js         // 封装响应的格式
|-- routes      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值