本系列分为四篇:
  • 建站四部曲之后端接口篇(SpringBoot+上线)
  • 建站四部曲之Python数据爬虫篇(selenium)
  • 建站四部曲之前端显示篇(React+上线)
  • 建站四部曲之移动端篇(Android+上线)

零、前言

本系列为了总结一下手上的知识,致敬我的2018
本篇的重点在于:用前两篇的数据使用React搭建一个简单网站
本篇总结的技术点:
React的组件封装React实现简单的懒加载React中的网络请求搜索功能
React中form表单与接口的对接路由react-router-dom的使用React中文件上传


先回顾一下服务端的接口(以ip:192.168.43.60,端口8089为例)
查询接口:GET请求

----查询所有:
http://192.168.43.60:8089/api/android/note
----查询偏移12条,查询12条(即12条为一页的第2页):
http://192.168.43.60:8089/api/android/note/12/12
----按区域查询(A为Android数据,SB为SpringBoot数据,Re为React数据)
http://192.168.43.60:8089/api/android/note/area/A http://192.168.43.60:8089/api/android/note/area/A/12/12
----按部分名称查询
http://192.168.43.60:8089/api/android/note/name/材料
http://192.168.43.60:8089/api/android/note/name/材料/2/2
----按类型名称查询(类型定义表见第一篇)
http://192.168.43.60:8089/api/android/note/name/ABCS
http://192.168.43.60:8089/api/android/note/name/ABCS/2/2
----按id名称查
http://192.168.43.60:8089/api/android/note/12

添改删接口

添-POST请求:http://192.168.43.60:8089/api/android/note
添-PUT请求:http://192.168.43.60:8089/api/android/note
删-DELETE请求:http://192.168.43.60:8089/api/android/note/1


一、首页的制作

1.网页效果(笔记本):已上线,可访问:www.toly1994.com

手机端用媒体查询简单适配了一下

2.示意图

这里的数据写死在了IndexData.js里,当然也可以让服务端提供数据,方便动态修改
只要格式和IndexData.js里的json对象保持一致就行了


3.路由的使用

由于主页比较简单,布局样式就不贴了,这里讲一下router的使用

3.1:安装
npm i react-router-dom
复制代码
3.2:新建一个router.js管理路由

其实也不是非常复杂,一句画来说就是:
http://http://192.168.43.60/Android可以访问到Android组件页面

import {BrowserRouter as Router, Route, Switch} from 'react-router-dom'
import React from 'react';
import Index from "./pagers/index/Index";
import Android from "./pagers/Android";
import SpringBoot from "./pagers/SpringBoot";
import ReactJS from "./pagers/ReactJS";
import Note from "./pagers/Note";export default () => (<Router><Switch><Route path={'/index'} component={Index}/><Route path={'/Android'} component={Android}/><Route path={'/SpringBoot'} component={SpringBoot}/><Route path={'/ReactJS'} component={ReactJS}/><Route path={'/Note'} component={Note}/><Route path={'/'} component={Index}/></Switch></Router>
)
复制代码
3.3:使用
ReactDOM.render(router(), document.getElementById('root'));
复制代码
3.4:跳转:
a标签的href和Link组件的to都可以,如果跳到Android页,写上`/Android`就行了
复制代码

二、单条目的封装:


1.组件状态:

核心是itemInfo,字段名称与接口数据保持一致

this.state = {top: "100%",itemInfo: {type: "数据读写",name: "1-SI--安卓SQLite基础使用指南",jianshuUrl: "https://www.jianshu.com/p/58076ca06a33",imgUrl: "http://192.168.43.60:8089/imgs/android/f593dab6a21907dec2dfed6ffc39b7e4.png",createTime: "2018-08-26",info: "零、前言 [1]熟悉MySQL的学这个就像会西瓜的人去学吃哈密瓜一样简单。[2]如果对MySQL不太熟悉的童鞋,可以看一下我的这篇:Spring..."}
}
复制代码

2.组件属性和行为
//组件属性
this.props.itemInfo:上层组件传递来的数据
this.props.isNew :是否加"新"字
this.props.css: 暴露样式修改接口(主要为了修改宽高)//组件行为:
鼠标进入是遮罩层+介绍文字进入+图片放大
复制代码

3.分析布局层级关系

4.标签的书写

使用top的变化来让悬浮时文字移入

<div className={"ItemBox"} style={{width: "300px", height: "200px"}}><div className={"box-img-bg"}style={{backgroundImage: `url(${this.state.itemInfo.imgUrl})`}}></div><div className="mask-with-text"onMouseEnter={() => {let itemInfo = this.state.itemInfo;this.setState({top: 0, itemInfo})}}onMouseLeave={() => {let itemInfo = this.state.itemInfo;itemInfo.text = "";this.setState({top: "100%", itemInfo})}}><div className="tag"><a href="">{this.state.itemInfo.type}</a></div><div className={"text"} style={{paddingTop: this.state.top}}><a href={this.state.itemInfo.jianshuUrl} target={"_blank"}>{this.state.itemInfo.info}</a></div></div><div className={"box-info"}><div className={ "new"}></div><div className={"text-info"}><a href={this.state.itemInfo.jianshuUrl} target={"_blank"}>{this.state.itemInfo.name}</a></div></div>
</div>
复制代码

5.scss样式书写
//使用flex布局并内容居中
@mixin flexCenter() {display: flex;justify-content: center;align-items: center;
}//宽高同父控件
@mixin match-parent() {width: 100%;height: 100%;
}//文字单行加省略号
@mixin text-single() {font-weight: bold;text-align: center;display: inline-block;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;
}//a标签的统一处理
@mixin handleA() {a {color: #fff;&:hover {color: #4B86FF;text-decoration: underline;}}
}.ItemBox {margin-top: 16px;border-radius: 10px;position: relative;overflow: hidden;box-shadow: rgba(214, 214, 214, .8) 1px 1px 2px 2px;&:hover {.mask-with-text {transition: background-color .5s cubic-bezier(0, 0.51, 1, 1);background-color: rgba(0, 0, 0, .5);}.box-img-bg {transition: transform .5s cubic-bezier(0, 0.51, 1, 1);transform: scale(1.2);}}.box-img-bg {border-radius: 10px;position: relative;background-size: 100%;background-repeat: no-repeat;@include match-parent;}.mask-with-text {.tag {background-image: url("../static/imgs/tag.svg");font-size: 10px;text-align: center;width: 65px;height: 65px;position: absolute;background-size: 100% 100%;right: -2px;top: -20px;@include flexCenter;@include handleA;}border-radius: 10px 0 0 10px;position: absolute;left: 0;top: 0;@include match-parent;@include flexCenter;.text {transition: padding-top .6s;padding-left: 20px;padding-right: 20px;@include handleA;}}.box-info {position: absolute;bottom: 0;width: 100%;height: 25%;background-color: rgba(0, 0, 0, .5);@include flexCenter;.new {background-image: url("../static/imgs/new.svg");align-self: flex-start;width: 30px;height: 30px;position: absolute;left: 0;background-size: 30px 30px;}.text-info {@include handleA;width: 80%;@include text-single()}}
}复制代码

6.静态界面组件化(属性对接):
 <div className={"ItemBox"} style={this.props.css}>
复制代码
componentDidMount() {this.setState({itemInfo: this.props.itemInfo})
}
复制代码

三、获取数据,填充界面


1.数据的获取(以Android界面为例)
1.1:添加依赖

这里使用axios发送请求

npm i axios
复制代码
1.2:获取数据方法简单封装:DataFetcher.js

封装一下是为了更符合接口的操作,以便复用

const axios = require('axios');
const BASE_URL = 'http://192.168.43.60:8089';
const API = '/api/android/note/';export default class DataFetcher {static findAll(callback, style = '', offset = 0, num = 10000) {let s = BASE_URL + API + style + "/" + offset + "/" + num;console.log(s);axios.get(s).then(rp => {callback(rp.data.data)});}static findAndroid(callback, offset = 0, num = 10000) {DataFetcher.findAll(callback, 'area/A', offset, num)}}
复制代码
1.3:使用方法:
DataFetcher.get(data => {console.log(data);
}, 'area/A');
复制代码

2.Pager页的实现

数据获取了,就已经万事具备

2.1.Pager的状态与属性:
//Pager的状态
this.state = {data: []
}//Pager的状态属性
this.props.img 背景图
this.props.type 类型
this.props.sub_title 副标题
this.props.title标题
复制代码
2.2.数据获取,更新状态
componentDidMount() {DataFetcher.get(data => {this.setState({data})}, this.props.type);
}
复制代码
2.3.根据数据生成视图
renderBody() {return (this.state.data.map((i, index) => {return (<ItemBox key={index} itemInfo={i}isNew={index < 3}css={{width: "30%", height: "100%"}}></ItemBox>);}))
}
复制代码

2.4.使用

只要改变: pager就能加载不同类型的数据

class Android extends Component {render() {return (<div><Pagerpager={{img: Logic.loadImg("android.svg"),title: "Android 技术栈",sub_title: "A complete node and summary for Android.",type: "area/A"}}/></div>);}
}
复制代码

3.懒加载的实现
3.1:问题所在:

问题所在:请求时是所以数据,遍历时所有条目都会加载
解决方案:查询范围的接口,监听滚动事件,快到底部时加载更多


3.2:滚动监听:
this.state = {dataCount: 9,//默认加载9条data: []
}
复制代码
componentDidMount() {let self = this;window.onscroll = () => {let scrollHeight = document.body.scrollHeight;let top = document.documentElement.scrollTop || document.body.scrollTop;if (scrollHeight - (top + document.body.clientHeight) < 80) {self.state.dataCount += 6;//每次多加载6条DataFetcher.get((data) => {this.setState({data})}, this.props.type, 0, this.state.dataCount);}};DataFetcher.get(data => {this.setState({data})}, this.props.type, 0, this.state.dataCount);
}
复制代码

四、搜索功能的实现:

折腾了好一会,总算摆弄处理了,期间犯了一个低级失误,mark一下: 搜索时记得在条目的:componentWillReceiveProps(nextProps)里更新state


1.查找组件的封装

很简单,样式上面的自己怎么好看怎么来吧
回顾一下按部分名称查询接口:http://192.168.43.60:8089/api/android/note/name/材料

export default class Searcher extends Component {constructor() {super();this.state = {text: ""}}render() {return (<div className={"pager-search"}><input className="input-search" defaultValue={this.props.searcher.text}onInput={(e) => {this.setState({text: e.target.value});}}></input><img src={Logic.loadImg('search3.svg')} alt=""onClick={() => {this.props.searcher.doOnClick(this.state.text)}}/></div>)}
}复制代码

2.样式
.pager-search {position: absolute;right: 0;top: 0;padding: 10px;display: flex;justify-content: space-around;input {padding: 6px;box-shadow: #EAEAEA 1px 1px 30px 1px;width: 60%;color: #cccccc;border-bottom: transparent;border-width: 1px;background-color: rgba(195,243,231,.5);border-radius: 10px;&:focus {color: black;}}img {width: 50px;&:hover {transition: transform .5s;transform: scale(1.2);fill: blue;}}
}
复制代码

3.请求方法的提取

这里定义了一个变量盛放type

let type = '';componentDidMount() {type = this.props.pager.type;//为type赋值//....
}getData() {//抽取获取数据函数DataFetcher.get(data => {this.setState({data})}, type, 0, this.state.dataCount);
}
复制代码

4.搜索框的使用:
<Searchersearcher={{text: "张风捷特烈是谁?",doOnClick: (value) => {type = "name/" + value;this.getData();}}}/>
复制代码

5.最重要的一点:ItemBox.js
componentWillReceiveProps(nextProps) {this.setState({itemInfo: nextProps.itemInfo});
}
复制代码

其实搜索功能本身不难,有后台接口配合就行了


五、添加操作:

1.使用axios发送post请求,封装插入方法
static insert(obj) {let s = BASE_URL + API;let params = new URLSearchParams();params.append("type", obj.type);params.append("name", obj.name);params.append("imgUrl", obj.name);params.append("localPath", obj.localPath);params.append("jianshuUrl", obj.jianshuUrl);params.append("juejinUrl", obj.juejinUrl);params.append("createTime", obj.createTime);params.append("info", obj.info);params.append("area", obj.area);axios.post(s, params).then(function (response) {alert(response.data.data);}).catch(function (error) {console.log(error);});
}
复制代码

2.测试插入数据的使用
DataFetcher.insert({type: "C",name: "hell0",localPath: "hell0",jianshuUrl: "hell0",juejinUrl: "hell0",createTime: "2018-12-13",info: "hell0",area: "A"
});
复制代码

3.使用axios上传文件方法封装
static upload(name,file) {let s = BASE_URL + "/api/android/upload";let fd = new FormData();fd.append(name, file);let config = {headers: {'Content-Type': 'multipart/form-data'}};axios.post(s, fd, config).then(res => {console.log(res)}).catch(res => {console.log(res)})
}
复制代码

4.上传方法的使用
<form id={"add-form"} onSubmit={this.handleSubmit.bind(this)} method={"post"} name={"add"}<label>上传图片:<input type="file" name={"file"}/></label><input type="submit" value="提交"/>
</form>
复制代码
//执行上传
handleSubmit(event) {let input = document.forms['add'].file;DataFetcher.upload("file", input.files[0]);event.preventDefault();
}
复制代码

六、React项目的上线

1.package.json配置homepage
 "homepage": "http://toly1994.com"
复制代码
2.打包
build一下,将生成的build文件加拷贝到服务器
复制代码
3.运行:确保服务器上有node,并且有serve

没有serve的话:npm i serve

serve -p 80 -s
复制代码

>那个jQuery随意操纵dom的时代已经一去不复返了,React的思想非常符合Android
我经常把React自定义组件和Android自定义控件去比较:
React组件接收的props就像Android自定义控件中的自定义属性,并且React灵活很多
css的布局就像Android中的布局,相比而言,css强大很多
ES6的语法加持,更让React写起来符合Javaer的心情,所以React写起来很舒心
复制代码

终于打完收工,前端我是打酱油的,不当之处,还请海涵。
下一站,安卓移动端(命属),敬请期待。


后记:捷文规范

1.本文成长记录及勘误表
项目源码 日期 备注
V0.1 2018-12-13 [建站四部曲之前端显示篇(React+上线)](www.jianshu.com/p/b0b4776cc…
2.更多关于我
笔名 QQ 微信 爱好
张风捷特烈 1981462002 zdl1994328 语言
我的github 我的简书 我的掘金 个人网站
3.声明

1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持


建站四部曲之前端显示篇(React+上线)相关推荐

  1. 建站四部曲之移动端篇(Android+上线)

    本系列分为四篇: 建站四部曲之后端接口篇(SpringBoot+上线) 建站四部曲之Python数据爬虫篇(selenium) 建站四部曲之前端显示篇(React+上线) 建站四部曲之移动端篇(And ...

  2. 建站四部曲之后端接口篇(SpringBoot+上线)

    本系列分为四篇: 建站四部曲之后端接口篇(SpringBoot+上线) 建站四部曲之Python数据爬虫篇(selenium) 建站四部曲之前端显示篇(React+上线) 建站四部曲之移动端篇(And ...

  3. 建站四部曲之Python爬虫+数据准备篇(selenium)

    本系列分为四篇: 建站四部曲之后端接口篇(SpringBoot+上线) 建站四部曲之Python数据爬虫篇(selenium) 建站四部曲之前端显示篇(React+上线) 建站四部曲之移动端篇(And ...

  4. 你不知道的事-建站始末1【准备篇】

    本篇内容会有些长,希望各位看官可以认真的阅读下去,我相信肯定会有收获. 写在前面 蝴蝶眨几次眼睛,才学会飞行,夜空洒满了星星,但几颗会落地. --你不知道的事 蝴蝶眨眼睛?星星会落地?当然很多人会认为 ...

  5. 第一章:腾讯云轻量应用服务器建站流程(前端)

    本文章介绍如何通过腾讯云轻量级服务器搭建前端页面的流程,中间涉及到了个人建站时踩得坑.望能给予大家一些帮助. 1.涉及内容有: 购买服务器与部分选项操作 宝塔面板功能选择及相关操作 前端代码部署 解决 ...

  6. 京东云助力企业“云端建站”,一站式网站建设服务正式上线

    近日,京东云宣布以软件即服务(SaaS)的方式对外提供一站式网站建设服务,包括定制类建站服务及模板类建站服务.京东云开放云端建站服务,可极大程度的简化网站建设的复杂步骤,无需专业技能即可轻松完成建站. ...

  7. 老榕智能建站软件_2020年,10大最佳免费建站软件

    文章目录 1 10大最佳免费建站软件 1.1 1. Site123 –是否像1-2-3一样容易? 1.2 2. Wix –国际重量级 1.3 3. Weebly –一个缺点很大的网站建设者 1.4 4 ...

  8. 闪灵CMS学校建站系统模板 含小程序

    介绍: 闪灵CMS学校建站系统(含小程序) v3.0 build20180905 更新说明 1.修复:修复后台自定义设置在插入带引号的文本自动转码的问题 2.修复:修复了手机模板产品及新闻分页链接只显 ...

  9. 上线文件服务器域名怎么建站,怎么做网站?建站详细流程

    搭建网站步骤包括了从网站文案及建站策划.前端设计及后台开发.域名及服务器选择.上线及后期维护等. 建网站流程步骤 做一个网站需要用到多方面的技术,新手建站人员可能对此不怎么了解,在这里为大家分享做网站 ...

最新文章

  1. Error:java: 错误: 不支持发行版本 14
  2. 给SQL数据库表和字段添加描述信息
  3. 0428(字典,列表,循环)
  4. python基础指令-Python基础——与Python的指令交互
  5. 计算机网络工程与菅理,网络工程与管理
  6. 15+ tar command usages with examples – Unix/Linux--reference
  7. 为何单线程的 Redis 却能支撑高并发?
  8. MySQL-InnoDB究竟如何巧妙实现,4种事务的隔离级别
  9. 64bit win7+VS2013+opencv2.4.9配置
  10. 计算机批量管理,如何将计算机电脑批量加入域
  11. win7下更改为achi硬盘模式
  12. python爬虫代码示例 动态_python动态爬虫的实例分享
  13. C语言--输入一个数判断是否为素数(多种方法)
  14. 基于STM8S003F3的数字温度计制作
  15. 树莓派开发笔记(十):Qt读取ADC模拟量电压(ADS1115读取电压模拟量)
  16. 【网络通讯开发系列】如何使用C语言编程通过UDP通讯解析域名
  17. adb 无线wifi调试
  18. linux内核 初始化 wifi,Linux驱动(六)----Wifi基础
  19. AI如何识别西瓜和冬瓜?
  20. 【poj3311】Hie with the Pie

热门文章

  1. Window CMD快捷键
  2. sqlserver中将行数据转为Xml文件格式
  3. Help Jimmy(递归)
  4. 可拖拽的ImageButton
  5. Freemaker FTL指令常用标签及语法
  6. [Google Guava] 使用和避免null
  7. Android5.1.1 - zygote中获取系统服务时抛出异常
  8. java向MySQL插入当前时间的四种方式和java时间日期格式化的几种方法(案例说明)...
  9. 用defy来潜水最终还是挂了........
  10. 页面自动刷新html实现