2019年最新 React从入门到实战(带 React 企业级实战项目-宜居)
(React基础知识&)
React基础知识&
1.React 学习前期准备
(React 学习前期准备&)
React 学习前期准备&
react环境
工程化,webpack安装node的npm
创建react项目
打开控制台
Webpack构建工具环境,默认端口3000
Public主入口文件,index与logo
Src源码文件,
Package.json当前依赖版本
2.React JSX语法
(React JSX语法&)
React JSX语法&
JSX基础语法
ReactDom.render渲染函数,第一个参数标签结构直接包含标签的JSX语法js+XML。React没有双引号概念,第二个参数获取一个元素
大括号就是JavaScript的语法,遇到<>安装HTML解析遇到{}按照js语法解析
import React from 'react';
import ReactDOM from 'react-dom';
import App from "./app"
// 全家桶
// document.getElementById('root')获取要插入的容器
// jsx语法:Hello React
// const react = "React";
// ():如果存在标签结构,并且标签结构要换行,需要用()括起来
// function tick(){
// const element = (
//
// Hello, world!
// It is { new Date().toLocaleTimeString() }
//
// )
// ReactDOM.render(element, document.getElementById('root'));
// }
// setInterval(tick,1000);
ReactDOM.render( , document.getElementById('root'));
3.React 元素渲染
(React 元素渲染&)
React 元素渲染&
Const element = () 小括号,如果存在标签结构并且一行不够放要换行使用()括起来。
当前时间通过js获取,把element当成一个元素代表标签元素。
没有调用element不存在,要让函数包裹ReactDOM
{}渲染元素标签方法
4.React 组件基础之创建组件
(React 组件基础之创建组件&)
React 组件基础之创建组件&
React组件创建
类的形式或者Hook方式创建组件,render(){}渲染函数中做想要做的事情,外部引用需要导出App
React所有东西都是组件组成的,降低耦合性
内容多增加小括号
连起来写法
组件互相引用以标签的形式引用
import React from "react"
// import Home from "./Home"
// import MyNav from "./MyNav"
// import StateComponent from "./StateComponent";
// import ComponentLife from "./ComponentLife"
import SetStateDemo from "./setStateDemo"
import IfDemo from "./ifDemo"
import KeyDemo from "./KeyDemo"
import FormDemo from "./FormDemo"
import RefsAndDOM from "./RefsAndDOM"
import RefsForm from "./RefsForm"
import Parent from "./components/parent"
import Compose from "./compose"
import PropsTypeDemo from "./PropsTypeDemo"
// 用类的形式创建组件,Hook形式
class App extends React.Component{
constructor(){
super();
this.state = {
title:"文本1"
}
}
clickChange = (data) =>{
this.setState({
title:data
})
}
// 渲染函数
render(){
// const nav1 = ["首页","视频","学习"];
// const nav2 = ["WEB","Java","Node"];
return(
{/* Hello React Component
学习React,最重要的是,心态要好!
*/}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/*
我是组合效果
*/}
)
}
}
export default App
import React from "react"
export default class Home extends React.Component{
constructor(props){
super(props);
// this.clickHandler = this.clickHandler.bind(this);
}
clickHandler(element,event){
// this无指向
// console.log(this);
console.log(element,event);
}
// apply call bind:面试常见问题
render(){
const names = ['iwen','ime'];
return(
Home
{/* */}
{/* */}
{/* */}
{
names.map((element,index) => {
// return - { element }
return - this.clickHandler(element, e) } key={index}>{ element }
})
}
)
}
}
5.React Props属性
(React Props属性&)
React Props属性&
props属性组件复用
组件复用性被多次使用呈现不同的数据,组件内容要动态生成
组件多次使用,传入nav,创建两个MyNav
MyNav来接收数据,组件被调用两次,列表渲染this.props.nav通过map进行遍历
不加key报警号,传入数据进行解析
Return结构中要加注释,遇到大括号要js解析
一个组件传入多个数据
Props不可以被修改,属于App.js只能在App.js中修改
import React from "react"
// props不可以被修改
export default class MyNav extends React.Component{
render(){
return(
{/* jsx语法 */}
{ this.props.title }
{
this.props.nav.map((element,index) =>{
return - { element }
})
}
)
}
}
6.React State状态
(React State状态&)
React State状态&
组件state状态属性
以前都是操作Dom元素,通过改变state来修改页面,通过在构造函数中this.state的方式来定义状态,通过this.state.count来获取值,count就是状态。请求数据也通过state展示
两个事件在外界定义,通过setState来改变值,this要绑定bind(this),在外部函数才能获取this,this.setState({})state本身是一个对象{},所有读state都必须this.state
除了bind绑定this,还有一种方式通用箭头函数改变this指向
动态文本显示不同数据
引用不需要大括号,是组件本身
import React from "react"
export default class StateComponent extends React.Component{
/**
* 组件中的状态:state
* 以前我们操作页面的元素的变化,都是修改DOM,操作DOM
* 但是有了React优秀的框架,我们不在推荐操作DOM,页面元素的改变使用State进行处理
*/
constructor(props){
super(props);
// 定义
this.state = {
count:10,
flag:true
}
}
increment(){
// setState
this.setState({
count:this.state.count+=1
})
}
decrement(){
this.setState({
count:this.state.count-=1
})
}
clickHandler = () =>{
console.log(this);
}
render(){
let showView = this.state.flag ? '我是孙悟空' : '我是假的孙悟空'
return(
组件的State
{ this.state.count }
{ showView }
)
}
}
7.React 组件生命周期函数
(React 组件生命周期函数&)
React 组件生命周期函数&
React生命周期函数,ComponentWillMount在组件渲染之前执行,钩子函数在不同阶段自动执行
ComponentDidMount组件渲染之后,组件已经呈现在页面运行状态,执行,
改变state执行shouldComponentUpdate返回true代表允许改变,false不允许改变还是原来状态。
返回true,执行componentDidUpdate数据改变之前执行,componentDidUpdate数据渲染完成。
Props发生改变执行componentWillReceiveProps,
组件销毁前执行ComponentWillMount,一共七个
先执行ComponentDid/WillMount
解构赋值直接读取值
点击修改执行Update
修改父元素执行componentWillReceiveProps,父传子
事件子传递给父,通过儿子事件触发父事件的执行,儿子调用父亲事件可以传递参数
父组件接收子组件的数据
import React from "react"
export default class ComponentLife extends React.Component{
constructor(props){
super(props);
this.state = {
count:10
}
}
componentWillMount(){
console.log("componentWillMount");
}
componentDidMount(){
console.log("componentDidMount");
}
shouldComponentUpdate(){
console.log("shouldComponentUpdate");
return true;
}
componentWillUpdate(){
console.log("componentWillUpdate");
}
componentDidUpdate(){
console.log("componentDidUpdate");
}
componentWillReceiveProps(){
console.log("componentWillReceiveProps");
}
componentWillUnmount(){
console.log("componentWillUnmount");
}
changeHandler = () =>{
this.setState({
count:this.state.count+=1
})
}
clickChange = () => {
this.props.clickChanges('我是儿子的数据');
}
render(){
const { count } = this.state;
return(
生命周期函数:{ count } - { this.props.title }
)
}
}
import React from "react"
// import Home from "./Home"
// import MyNav from "./MyNav"
// import StateComponent from "./StateComponent";
// import ComponentLife from "./ComponentLife"
import SetStateDemo from "./setStateDemo"
import IfDemo from "./ifDemo"
import KeyDemo from "./KeyDemo"
import FormDemo from "./FormDemo"
import RefsAndDOM from "./RefsAndDOM"
import RefsForm from "./RefsForm"
import Parent from "./components/parent"
import Compose from "./compose"
import PropsTypeDemo from "./PropsTypeDemo"
// 用类的形式创建组件,Hook形式
class App extends React.Component{
constructor(){
super();
this.state = {
title:"文本1"
}
}
clickChange = (data) =>{
this.setState({
title:data
})
}
// 渲染函数
render(){
// const nav1 = ["首页","视频","学习"];
// const nav2 = ["WEB","Java","Node"];
return(
{/* Hello React Component
学习React,最重要的是,心态要好!
*/}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/* */}
{/*
我是组合效果
*/}
)
}
}
export default App
8.React setState是同步还是异步
(React setState是同步还是异步&)
React setState是同步还是异步&
setState异步处理方案
调用setState会重绘视图,实时获取state值
每次获取值是上一次的值,异步通过回调函数获取实时获取的
同步实时获取
通过promise处理异步问题,resolve成功回调,所有改变调用setStaetAsync变为同步。
使用promise通过asyn和await进行处理,await执行完成之后才会执行后面的console.log。
标准函数写法要bind(this) promise async await
import React from "react"
export default class SetStateDemo extends React.Component{
constructor(){
super();
this.state = {
count:0
}
}
async increment(){
// this.setState({
// count:this.state.count+1
// },() => {
// console.log(this.state.count);
// })
await this.setStateAsync({count:this.state.count+1});
console.log(this.state.count);
}
// promise async 和 await
setStateAsync(state){
return new Promise((resolve) =>{
this.setState(state,resolve);
})
}
render(){
return(
setState同步还是异步问题
{ this.state.count }
)
}
}
9.React 条件渲染
(React 条件渲染&)
React 条件渲染&
条件渲染
数据来源于网络,如果空的数据不用渲染缺省值
import React from "react"
export default class IfDemo extends React.Component {
/**
* 常用的应用常见:
* 1.对视图条件进行切换
* 2.做缺省值
*/
constructor() {
super();
this.state = {
isLogin: false,
names: ["ime"]
}
}
clickHandler = () => {
this.setState({
isLogin: true
})
}
render() {
const { names } = this.state;
let showView = this.state.isLogin ?
iwen :
请登录
return (
条件渲染:{showView}
{
names.length > 0 ?
{
names.map((element, index) => {
return {element}
})
}
:
请等待数据正在请求....
}
)
}
}
10.React 列表渲染&key
(React 列表渲染&key&)
React 列表渲染&key&
map列表渲染key
Key加载到最外层标签元素,数组就可以遍历无论有多复杂的
二层遍历
Push一个对象
Push返回值不是当前数组,而是返回数组长度userinfo变为一个长度,使用concat合并
Key局部渲染,只在下面添加标签整个视图没有重新渲染,key唯一索引,只有索引变化才会渲染视图
import React from "react"
export default class KeyDemo extends React.Component{
constructor(){
super();
this.state = {
userinfo:[
{
name:"iwen",
age:20,
sex:"男",
jobs:['11','222','333']
},
{
name:"ime",
age:20,
sex:"男",
jobs:['11','222','333']
},
{
name:"frank",
age:20,
sex:"男",
jobs:['11','222','333']
}
]
}
}
clickHandler = () =>{
this.setState({
userinfo:this.state.userinfo.concat([{
name:"sakura",
age:30,
sex:"女",
jobs:['333','444','555']
}])
})
}
render(){
return(
{
this.state.userinfo.map((element,index) =>{
return(
-
{ element.name }
{ element.age }
{ element.sex }
{
element.jobs.map((childElement,childIndex) =>{
return { childElement }
})
}
)
})
}
)
}
}
11.React 表单受控组件
(React 表单受控组件&)
React 表单受控组件&
ref受控组件与非受控组件,表单提交preventDefault
受控组件表单内的value的值是state帮助管理的,非受控组件自己操作Dom。
受控组件的value值是constructor中的声明的state,value值被管理了。能改变state只有setState,通过onChange事件去改变value的值,value的值可以通过event对象获取。
表单默认跳转,组织默认事件
通过state管理读取state中的值,受控组件获取value不方便
import React from "react"
export default class FormDemo extends React.Component{
constructor(){
super();
this.state = {
value:""
}
}
handleSubmit = (e) =>{
e.preventDefault();
console.log(this.state.value);
}
onChangeHandler = (e) =>{
this.setState({
value:e.target.value
})
}
render(){
return(
)
}
}
12.React Refs&DOM
(React Refs&DOM&)
React Refs&DOM&
组件比较多使用非受控组件,不推荐直接操作Dom一些额外情况可以直接操作DOM
获取div dom元素
DidMount说明div已经渲染完毕了,存在了
如果ref是一个字符串,官方已经废弃
import React from "react"
export default class RefsAndDOM extends React.Component{
constructor(){
super();
this.HelloDiv = React.createRef();
}
componentDidMount(){
this.HelloDiv.current.style.color = "red";
}
render(){
return(
Refs和DOM
Hello
)
}
}
13.React 表单 非受控组件
(React 表单 非受控组件&)
React 表单 非受控组件&
数据不再以受控组件获得,实时获取,current获取元素div结构,获取元素值
不用每一个input增加一个事件
推荐使用受控组件,如果有很多事件使用非受控组件
有点不用每个input标签实现一个事件
import React from "react"
export default class RefsForm extends React.Component{
constructor(){
super();
this.username = React.createRef();
this.password = React.createRef();
}
clickHandler = (e) =>{
console.log(this.username.current.value);
console.log(this.password.current.value);
}
render(){
return(
)
}
}
14.React 状态提升
(React 状态提升&)
React 状态提升&
状态提升是用来进行组件之间数据交互,推荐受控组件
1和2都去接收数据,ComponentDidMount一进入,传过来数据动态修改
互相之间不再是独立的状态,1,2互相影响传递数据,状态要同步的
值应该从props中获取,互相影响
import React from "react"
import Child1 from "./child1"
import Child2 from "./child2"
export default class Parent extends React.Component{
constructor(){
super();
this.state = {
money:1
}
}
changeHandler(e){
this.setState({
money:e.target.value
})
}
render(){
return(
Parent
人民币:
美元:
)
}
}
import React from "react"
export default class Child1 extends React.Component{
constructor(){
super();
this.state = {
input1:0
}
}
componentDidMount(){
this.setState({
input1:this.props.money
})
}
changeHandler(e){
this.setState({
input1:e.target.value
})
}
render(){
return(
{this.props.money}
)
}
}
import React from "react"
export default class Child2 extends React.Component {
constructor(){
super();
this.state = {
input2:0
}
}
componentDidMount(){
this.setState({
input2:this.props.money * 7
})
}
changeHandler(e){
this.setState({
input2:e.target.value
})
}
render() {
return (
{this.props.money * 7}
)
}
}
15.React 组件组合
(React 组件组合&)
React 组件组合&
PropsType验证
组件引用的中间
读到组件间的div元素
import React from "react"
export default class Compose extends React.Component{
render(){
return(
哈哈哈:{ this.props.children }
)
}
}
16.React PropsType验证
(React PropsType验证&)
React PropsType验证&
类型检查增强程序的健康性
Props接收标题文本,传递数据类型
isRequire是必选项,必须呈现内容
缺省默认props值
import React from 'react'
import PropTypes from 'prop-types';
export default class PropsTypeDemo extends React.Component{
render(){
return(
Hello:{ this.props.title }
)
}
}
// PropsTypeDemo.propTypes = {
// title:PropTypes.number.isRequired
// }
PropsTypeDemo.propTypes = {
title:PropTypes.string
}
PropsTypeDemo.defaultProps = {
title:'默认值'
}
(Antd UI框架&)
Antd UI框架&
17.React Antd UI组件库引入
(React Antd UI组件库引入&)
React Antd UI组件库引入&
Css全局引用放在最外层,很多地方用到组件库
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
ReactDOM.render( , document.getElementById('root'));
import React from 'react';
import { Button,Pagination } from 'antd';
// import Button from 'antd/es/button';
// import 'antd/es/button/style/css';
// import Pagination from 'antd/es/pagination';
// import 'antd/es/pagination/style/css';
function App() {
function pageChange(page, pageSize){
console.log(page, pageSize);
// 网络请求
}
return (
);
}
export default App;
18.React Antd 按需加载
(React Antd 按需加载&)
React Antd 按需加载&
Antd按需加载
Antd库非常大,按需加载,手动引入
直接安装依赖修改文件,正常加载即可
没有webpack配置文件,被隐藏了
显示隐藏文件,删除git
安装之后npm start跑起来
之后就可以按需加载了
退出运行状态crtl+c
"babel": {
"presets": [
"react-app"
],
"plugins": [
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "es",
"style": "css"
}
]
]
},
"devDependencies": {
"babel-plugin-import": "^1.12.2"
}
19.React Antd 属性介绍
(React Antd 属性介绍&)
React Antd 属性介绍&
分页组件
分页做网络请求事件
import React from 'react';
import { Button,Pagination } from 'antd';
// import Button from 'antd/es/button';
// import 'antd/es/button/style/css';
// import Pagination from 'antd/es/pagination';
// import 'antd/es/pagination/style/css';
function App() {
function pageChange(page, pageSize){
console.log(page, pageSize);
// 网络请求
}
return (
);
}
export default App;
(Fetch 网络请求&)
Fetch 网络请求
20.React Fetch get请求
(React Fetch get请求&)
React Fetch get请求&
Jsx有更好提示
重启识别
fetch基于promise
DidMount(),fetch网络请求地址,then()上一个return返回的数据
Res.JSON()代表返回
fetch的post请求封装
import React from 'react';
import qs from "querystring"
import ProxyDemo from "./ProxyDemo"
import api from "./api"
export default class App extends React.Component {
constructor(props){
super(props);
this.state = {
banners:[]
}
}
componentDidMount(){
/**
* fetch 基于promise
*
* https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
*
* get
*/
fetch("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php")
.then(res => res.json())
.then(data =>{
this.setState({
banners:data.banner
})
})
/**
* post
*
* ajax:对象类型的参数
* body:字符串类型
*/
fetch("http://iwenwiki.com/api/blueberrypai/login.php",{
method:"POST",
headers:{
'Content-Type': 'application/x-www-form-urlencoded',
"Accept":"application/json,text/plain,*/*"
},
// 自己字符串拼接方法
body:qs.stringify({
user_id:"[email protected]",
password:"iwen123",
verification_code:"crfvw"
})
// body:"[email protected]&password=iwen123&verification_code=crfvw"
}).then(res => res.json())
.then(data =>{
console.log(data);
})
api.getChengpin().then(res => res.json()).then(data =>{
console.log(data);
})
api.getLogin({
user_id:"[email protected]",
password:"iwen123",
verification_code:"crfvw"
}).then(res => res.json()).then(data =>{
console.log(data);
})
}
render(){
const { banners } = this.state;
return(
{
banners.length > 0 ?
{
banners.map((element,index) =>{
return - { element.title }
})
}
: 等待数据加载...
}
)
}
}
21.React Fetch post请求
(React Fetch post请求&)
React Fetch post请求&
访问请求方式是post
Ajax是字符串类型
对象写法的qs
22.React Fetch 配置package文件解决跨域
(React Fetch 配置package文件解决跨域&)
React Fetch 配置package文件解决跨域&
Package.json增加proxy解决跨域
前面不需要了,已经被配置代替了
产生错误解决
修改配置文件Crtl+c退出运行状态重新运行
跨域解决方案,catch除以异常
import React from "react"
export default class ProxyDemo extends React.Component{
/**
* https://yunp.top/blog/index.php/2016/05/12/44/
*
* http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.billboard.billList&type=1&size=10&offset=0
*/
/**
* 跨域的解决方案:
* 开发模式下:
* 利用环境解决:react vue常用框架,都提供了解决方案
* 生产模式下:
* jsonp cors iframe postMessage...
*
*
* npm run build:打包 -> 生产模式
*/
// https://github.com/facebook/create-react-app/blob/master/docusaurus/docs/proxying-api-requests-in-development.md
componentDidMount(){
// proxy:http://tingapi.ting.baidu.com
// fetch("/v1/restserver/ting?method=baidu.ting.billboard.billList&type=1&size=10&offset=0")
// .then(res => res.json())
// .then(data =>{
// console.log(data);
// })
// // 失败了
// .catch(error =>{
// console.log(new Error(error));
// })
// fetch("/api/list")
// .then(res => res.json())
// .then(data =>{
// console.log(data);
// })
}
render(){
return(
Hello
)
}
}
package.json
package.json
{
"name": "react-fetch-demo",
"version": "0.1.0",
"private": true,
"dependencies": {
"express": "^4.17.1",
"http-proxy-middleware": "^0.20.0",
"react": "^16.10.2",
"react-dom": "^16.10.2",
"react-scripts": "3.2.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
23.React Fetch 手动配置跨域
(React Fetch 手动配置跨域&)
React Fetch 手动配置跨域&
mock跨域
创建app对象,前台3000端口,后台3100端口
增加网络请求地址
App.use根路径与路由对象
开启新的窗口
前台不能访问3100后台,
手动配置跨域解决方案
访问服务器3100端口,通过api代替地址
开发中常用的方式
mock/index.js
const express = require("express")
const app = express();
const router = require("./router");
app.use("/",router);
app.listen(3100,function(){
console.log("serve running at port 3000");
})
mock/router.js
const express = require("express");
const router = express.Router();
router.get("/api/list",(req,res) =>{
res.send([
{
name:"iwen",
age:20
},
{
name:"ime",
age:30
}
])
})
module.exports = router;
src/setupProxy.js
// const proxy = require('http-proxy-middleware');
// module.exports = function (app) {
// app.use(
// '/api',
// proxy({
// target: 'http://localhost:3100',
// changeOrigin: true,
// })
// );
// };
24.React Fetch 封装网络请求
(React Fetch 封装网络请求&)
React Fetch 封装网络请求&
封装网络请求,ctrl+c停止服务器
使用封装网络请求,base基础公共路径,chengpin是配置路径
导出api在任何地方都可以使用了
Params已经处理了
封装fetch网络请求
src/utils/http.js
/**
* get post
*/
import qs from "querystring"
export function httpGet(url){
const result = fetch(url);
return result;
}
export function httpPost(url,params){
const result = fetch(url,{
method:"POST",
headers:{
'Content-Type': 'application/x-www-form-urlencoded',
"Accept":"application/json,text/plain,*/*"
},
/**
* {
* name:"iwen"
* }
*
* name=iwen
*/
body:qs.stringify(params)
})
return result;
}
src/api/base.js
const base = {
// http://iwenwiki.com/api/blueberrypai/getChengpinInfo.php
ownUrl:"http://iwenwiki.com",
chengpin:"/api/blueberrypai/getChengpinInfo.php",
login:"/api/blueberrypai/login.php"
}
export default base
src/api/index.js
import { httpGet,httpPost } from "../utils/http"
import base from "./base"
/**
* 有多少的网络请求,一次性就看到了
* redux:action集中在一起
*/
const api = {
getChengpin(){
return httpGet(base.ownUrl + base.chengpin);
},
getLogin(params){
return httpPost(base.ownUrl + base.login,params);
}
}
export default api
(React-Router路由配置&)
React-Router路由配置&
25.React-Router 路由介绍
(React-Router 路由介绍&)
React-Router 路由介绍&
Route路由组件
通过不同路径展示不同页面,router对象切换不同页面,最外层用弩switch对象包裹
import React from "react"
export default class Home extends React.Component {
render() {
return (
Home
)
}
}
import React from "react"
import querystring from "querystring"
import MineDemo from "./MineDemo"
const Mine = (props) =>{
// const params = new URLSearchParams(props.location.search)
// console.log(params.get("name"));
// console.log(params.get("age"));
// const value = querystring.parse(props.location.search);
// console.log(value);
// console.log(value.name);
// console.log(value.age);
const clickHandle = () =>{
// props.history.push("/");
// push 叠加的上一次的页面依然存在内中, replace是替换,上一次的页面不存在了
props.history.replace("/")
}
return(
Mine
)
}
export default Mine
import React from 'react';
import Home from "./pages/Home"
import Mine from "./pages/Mine"
import UCenter from "./pages/UCenter"
// import { BrowserRouter as Router, Route } from "react-router-dom";
import { HashRouter as Router, Route, Switch,Redirect } from "react-router-dom";
import Nav from "./components/Nav"
import NotFound from "./pages/NotFound"
import Demo from "./pages/Demo"
import Shop from "./pages/Shop"
import Book from "./pages/Book"
import WEBBook from "./pages/WEBBook"
import JavaBook from "./pages/JavaBook"
/**
* HashRouter:锚点链接
* BrowserRouter:h5新特性 / history.push 如果上线之后,需要后台做一些处理:重定向处理 404bug
*/
/**
* /mine/ucenter 包含了 /mine
*
*/
function App() {
return (
{/* Hello Demo }> */}
}>
{/* */}
);
}
export default App;
import React from "react"
import { Link,NavLink } from "react-router-dom";
import "./style.css"
export default class Nav extends React.Component {
render() {
return (
)
}
}
26.React-Router BrowserRouter 与 HashRouter
(React-Router BrowserRouter 与 HashRouter&)
React-Router BrowserRouter 与 HashRouter&
history重定向404
#号后展示路由信息
在#后面加路由
27.React-Router Link跳转
(React-Router Link跳转&)
React-Router Link跳转&
Link导航切换
导航点击跳转不同视图,Link实现页面跳转,to属性是一个路径
28.React-Router exact匹配规则
(React-Router exact匹配规则&)
React-Router exact匹配规则&
exact精准匹配
/mine/ucenter会显示mime和UCenter两个组件
精准匹配,不会匹配mime
简写
Home是根目录/
/路径都匹配,都会有Home
不会每一个都显示Home组件
import React from "react"
const UCenter = (props) =>{
// http://localhost:3000/#/mine/ucenter/1001
console.log(props);
return(
Hello UCenter:{ props.match.params.id } - { props.match.params.name }
)
}
export default UCenter
29.React-Router strict精准匹配
(React-Router strict精准匹配&)
React-Router strict精准匹配&
strict严格匹配
后面不能跟/,有/不匹配,要和exact精准匹配一起使用
30.React-Router 404页面和Switch
(React-Router 404页面和Switch&)
React-Router 404页面和Switch&
404页面用户体验
直接加Component全规则匹配
Switch只加载一个页面,404不能和其他页面一起显示
import React from "react"
const NotFound = () =>{
return(
404页面
)
}
export default NotFound
31.React-Router render func
(React-Router render func&)
React-Router render func&
简易Render加载组件
返回值是组件
传递数据三个点
接收参数
基本类型数据
简写
import React from "react"
const Demo = ({ name }) =>{
return(
Demo:{ name }
)
}
export default Demo
32.React-Router NavLink高亮
(React-Router NavLink高亮&)
React-Router NavLink高亮&
不知道现在在哪个页面下的,高亮显示,替换为NavLink高亮,多了一个样式
路径的包裹,点击都变红色
不需要css属性
33.React-Router URL Parameters
(React-Router URL Parameters&)
React-Router URL Parameters&
路由跳转携带参数,/冒号后参数的key,跳转的页面就可以接收参数
斜杠传递值
根据参数地址不同拿到不同数据展示
?页面参数可有可无的
跳转参数携带值,/后面跟地址
路由跳转参数传递
import React from "react"
const UCenter = (props) =>{
// http://localhost:3000/#/mine/ucenter/1001
console.log(props);
return(
Hello UCenter:{ props.match.params.id } - { props.match.params.name }
)
}
export default UCenter
34.React-Router query string读取参数
(React-Router query string读取参数&)
React-Router query string读取参数&
queryString获取?后参数的值
获取传递的name
取出整个对象,要手动去掉前面的?
URLSearchParams读取隐藏参数
import React from "react"
import querystring from "querystring"
import MineDemo from "./MineDemo"
const Mine = (props) =>{
// const params = new URLSearchParams(props.location.search)
// console.log(params.get("name"));
// console.log(params.get("age"));
// const value = querystring.parse(props.location.search);
// console.log(value);
// console.log(value.name);
// console.log(value.age);
const clickHandle = () =>{
// props.history.push("/");
// push 叠加的上一次的页面依然存在内中, replace是替换,上一次的页面不存在了
props.history.replace("/")
}
return(
Mine
)
}
export default Mine
35.React-Router Link to- object
(React-Router Link to- object&)
React-Router Link to- object&
Pathname地址
增加Search与hash属性
Link属性
import React from "react"
import { Link,NavLink } from "react-router-dom";
import "./style.css"
export default class Nav extends React.Component {
render() {
return (
)
}
}
36.React-Router redirect重定向
(React-Router redirect重定向&)
React-Router redirect重定向&
Redirect重定向
访问hellomine跳转到mine
检查是否未登录
前面一定有/否则404
不能登录跳转其他页面,首页/
import React from 'react';
import Home from "./pages/Home"
import Mine from "./pages/Mine"
import UCenter from "./pages/UCenter"
// import { BrowserRouter as Router, Route } from "react-router-dom";
import { HashRouter as Router, Route, Switch,Redirect } from "react-router-dom";
import Nav from "./components/Nav"
import NotFound from "./pages/NotFound"
import Demo from "./pages/Demo"
import Shop from "./pages/Shop"
import Book from "./pages/Book"
import WEBBook from "./pages/WEBBook"
import JavaBook from "./pages/JavaBook"
/**
* HashRouter:锚点链接
* BrowserRouter:h5新特性 / history.push 如果上线之后,需要后台做一些处理:重定向处理 404bug
*/
/**
* /mine/ucenter 包含了 /mine
*
*/
function App() {
return (
{/* Hello Demo }> */}
}>
{/* */}
);
}
export default App;
import React from "react"
import { Redirect,Prompt } from "react-router-dom"
export default class Shop extends React.Component{
state = {
isLogin:true,
name:""
}
render(){
const { isLogin } = this.state;
return(
{
isLogin ?
Shop
:
}
this.setState({name:e.target.value}) }/>
)
}
}
37.React-Router 重定向push和replace
(React-Router 重定向push和replace&)
React-Router 重定向push和replace&
代码实现重定向,要用const定义
Push点击跳转的路径,push是叠加上一次页面依然存在内存中,replace也没不存在了
push与replace
import React from "react"
import querystring from "querystring"
import MineDemo from "./MineDemo"
const Mine = (props) =>{
// const params = new URLSearchParams(props.location.search)
// console.log(params.get("name"));
// console.log(params.get("age"));
// const value = querystring.parse(props.location.search);
// console.log(value);
// console.log(value.name);
// console.log(value.age);
const clickHandle = () =>{
// props.history.push("/");
// push 叠加的上一次的页面依然存在内中, replace是替换,上一次的页面不存在了
props.history.replace("/")
}
return(
Mine
)
}
export default Mine
38.React-Router withRouter
(React-Router withRouter&)
React-Router withRouter&
要有this.props
withRouter
获取路由对象withRouter,就可以获得props了进行跳转
import React from "react"
import { withRouter } from "react-router-dom"
class MineDemo extends React.Component{
clickHandle(){
console.log(this.props);
this.props.history.push("/")
}
// 当前组件没有直接被路由管理,所以没有路由对象
// withRouter
render(){
return(
)
}
}
// 高阶组件
export default withRouter(MineDemo)
import React from "react"
import querystring from "querystring"
import MineDemo from "./MineDemo"
const Mine = (props) =>{
// const params = new URLSearchParams(props.location.search)
// console.log(params.get("name"));
// console.log(params.get("age"));
// const value = querystring.parse(props.location.search);
// console.log(value);
// console.log(value.name);
// console.log(value.age);
const clickHandle = () =>{
// props.history.push("/");
// push 叠加的上一次的页面依然存在内中, replace是替换,上一次的页面不存在了
props.history.replace("/")
}
return(
Mine
)
}
export default Mine
39.React-Router Prompt
(React-Router Prompt&)
React-Router Prompt&
Prompt导航离开页面之前做额外处理,不能白输入
判断是否存在,给用户提示
import React from "react"
import { Redirect,Prompt } from "react-router-dom"
export default class Shop extends React.Component{
state = {
isLogin:true,
name:""
}
render(){
const { isLogin } = this.state;
return(
{
isLogin ?
Shop
:
}
this.setState({name:e.target.value}) }/>
)
}
}
40.React-Router 路由嵌套
(React-Router 路由嵌套&)
React-Router 路由嵌套&
注册路由中显示
嵌套成子元素,唯一化switch
页面没有显示JavaBook,定义规则显示页面位置,可以嵌套很多层
props.children路由嵌套
import React from "react"
export default class Book extends React.Component{
render(){
return(
Book:
{/* 路由嵌套显示的位置 */}
{ this.props.children }
)
}
}
import React from "react"
export default class WebBook extends React.Component{
render(){
return(
WebBook
)
}
}
import React from "react"
export default class JavaBook extends React.Component{
render(){
return(
JavaBook
)
}
}