学习React之React应用

第1章 React应用(基于React脚手架)

1.1 使用create-react-app创建react应用

1.1.1 React脚手架
  1. 脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
    (1)包含了所有需要的配置(语法检查、jsx编译、devServer…)
    (2)下载所有相关依赖
    (3)可以直接运行简单效果
  2. react提供了一个用于创建react项目的脚手架库: create-react-app
  3. 项目的整体技术架构为: react + webpack + es6 + eslint
  4. 特点: 模块化, 组件化, 工程化
1.1.2 创建项目并启动
  1. 全局安装 npm i create-react-app -g
  2. 使用命令创建项目: create-react-app hello-react
  3. 启动项目: npm start
1.1.3 脚手架目录结构
public ---- 静态资源文件夹
		favicon.icon ------ 网站页签图标
		index.html -------- 主页面
		logo192.png ------- logo图
		logo512.png ------- logo图
		manifest.json ----- 应用加壳的配置文件
		robots.txt -------- 爬虫协议文件
src ---- 源码文件夹
		App.css -------- App组件的样式
		App.js --------- App组件
		App.test.js ---- 用于给App做测试
		index.css ------ 样式
		index.js ------- 入口文件
		logo.svg ------- logo图
		reportWebVitals.js
			--- 页面性能分析文件(需要web-vitals库的支持)
		setupTests.js
			---- 组件单元测试的文件(需要jest-dom库的支持)

1.2 配置代理

1.2.1 方法一

在package.json中追加如下配置

"proxy":"http://localhost:5000"

说明:

  1. 优点:配置简单,前端请求资源时可以不加任何前缀。
  2. 缺点:不能配置多个代理。
  3. 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)
1.2.2 方法二
  1. 第一步:创建代理配置文件, 在src下创建配置文件:src/setupProxy.js

  2. 编写setupProxy.js配置具体代理规则:

       const proxy = require('http-proxy-middleware')
    
    module.exports = function(app) {
     app.use(
       proxy('/api1', {  //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
         target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
         changeOrigin: true, //控制服务器接收到的请求头中host字段的值
         /*
         	changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
         	changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
         	changeOrigin默认值为false,但我们一般将changeOrigin值设为true
         */
         pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
       }),
       proxy('/api2', { 
         target: 'http://localhost:5001',
         changeOrigin: true,
         pathRewrite: {'^/api2': ''}
       })
     )
    }
    
  3. 优缺点:

    1. 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
    2. 缺点:配置繁琐,前端请求资源时必须加前缀

第2章 React ajax

2.1 使用

2.1.1 说明
  1. React本身只关注于界面, 并不包含发送ajax请求的代码
  2. 前端应用需要通过ajax请求与后台进行交互(json数据)
  3. 3.react应用中需要集成第三方ajax库(或自己封装)
2.1.2 常用库
  1. jQuery:比较重
  2. axios: 基于XmlHttpRequest对象的ajax,promise风格;可以在浏览器端和node服务端(封装的http模块)
  3. fetch: 原生发送请求
2.1.3 axios使用
  • axios.get()
  • axios.post
2.1.4 Fetch的使用
  1. 见MDN上的用法

2.3 消息订阅-发布机制

  1. 通过以上学习,目前组件之间的通信只能将状态提取到公共共有组件身上,然后利用props以及传递函数的方式实现交互。
  2. 兄弟组件之间可以利用消息订阅-发布机制来实现通信
2.3.1 PubSubJS
  1. 工具库: PubSubJS
  2. 下载: npm intall pubsub-js --save
  3. 使用:
    1. import PubSub from 'pubsub-js'//引入
    2. componentDidMount里订阅消息 PubSub.subscribe('delete', function(data){ }); //订阅
    3. PubSub.publish('delete', data)//发布消息
    4. 在订阅的组件销毁的时候需要取消订阅 , PubSub.unsubscrible(this.xxx)
  4. 通过以上就可以实现消息订阅与发布了

第3章 React路由

3.1 相关理解

3.1.1 SPA的理解
  1. 用三大框架开发的项目都是单页面应用,也就是整个应用只有一个完整的页面
  2. 点击页面的链家不会刷新页面,只会做页面的局部刷新
  3. 数据通过ajax请求获取,并且异步显示
3.1.2 路由的理解
  1. 什么是路由
    1. 一个路由就是一种映射关系(key: value)
    2. key为路径,value可能是function或者component
  2. 路由分类
    1. 前端路由:
      1. 浏览器端路由,value是component,用于展示页面内容。
      2. 注册路由:
      3. 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
    2. 后端路由:
      1. 理解: value是function, 用来处理客户端提交的请求。
      2. 注册路由: router.get(path, function(req, res))
      3. 工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
3.1.3 react-router-dom的理解
  1. react的插件库,专门用于实现SPA应用
  2. 基于react的项目基本上都会用到这个库
  3. 1.下载react-router-dom: npm install react-router-dom --save

3.2 路由组件与一般组件

	1.写法不同:
	一般组件:<Demo/>
	路由组件:<Route path="/demo" component={Demo}/>
	2.存放位置不同:
	 一般组件:components
	 路由组件:pages
	3.接收到的props不同:
		一般组件:写组件标签时传递了什么,就能收到什么
		路由组件:接收到三个固定的属性:history相关:go,goback,goForward,push,replace,location.pathname,state,search;match:params: {},path: "/about",url: "/about"													
														

3.3 路由的使用以及相关API

3.3.1 LinkBrowserRouterHashRouter
  1. 所有的路由都要受到router的管理,router分为两类:BrowserRouter(history跳转)和 HashRouter(hash跳转)
  2. a标签是怎么写的,Link就是怎么写
    index.js
//引入react核心库
import React from 'react'
//引入ReactDOM
import ReactDOM from 'react-dom'
//
import {BrowserRouter} from 'react-router-dom'
//引入App
import App from './App'

ReactDOM.render(
	<BrowserRouter>
		<App/>
	</BrowserRouter>,
	document.getElementById('root')
)

App.jsx

import React, { Component } from 'react'
import {Link,Route} from 'react-router-dom'
import Home from './components/Home'
import About from './components/About'

export default class App extends Component {
	render() {
		return (
			<div>
				<div className="row">
					<div className="col-xs-offset-2 col-xs-8">
						<div className="page-header"><h2>React Router Demo</h2></div>
					</div>
				</div>
				<div className="row">
					<div className="col-xs-2 col-xs-offset-2">
						<div className="list-group">

							{/* 原生html中,靠<a>跳转不同的页面 */}
							{/* <a className="list-group-item" href="./about.html">About</a>
							<a className="list-group-item active" href="./home.html">Home</a> */}

							{/* 在React中靠路由链接实现切换组件--编写路由链接 */}
							<Link className="list-group-item" to="/about">About</Link>
							<Link className="list-group-item" to="/home">Home</Link>
						</div>
					</div>
					<div className="col-xs-6">
						<div className="panel">
							<div className="panel-body">
								{/* 注册路由 */}
								<Route path="/about" component={About}/>
								<Route path="/home" component={Home}/>
							</div>
						</div>
					</div>
				</div>
			</div>
		)
	}
}

3.3.2 NavLink
  1. NavLink可以实现路由链接的高亮,通过activeClassName指定样式名.点击谁,就会给谁追加上active类名
  2. 如何封装avLink
    1. 封装
      <NavLink activeClassName="atguigu" className="list-group-item" {...this.props}/>
      
    2. 使用
      <MyNavLink to="/home">Home</MyNavLink>
      
  3. 标签体内容也可以在props的children里取到,所以可以用...props获取到传递的数据,
3.3.3 Switch的使用
  1. 因为路由匹配是匹配了还会继续往下匹配,所以就可以用到switch;通常情况下,path和component是一一对应的关系;Switch可以提高路由匹配效率(单一匹配)。
    <Switch>
    	<Route path="/about" component={About}/>
    	<Route path="/home" component={Home}/>
    	<Route path="/home" component={Test}/>
    </Switch>
    
3.3.4 解决多级路径刷新页面样式丢失的问题
  1. public/index.html 中 引入样式时不写 .//(常用)
  2. public/index.html 中 引入样式时不写 ./ 写 %PUBLIC_URL%(常用)
  3. 使用HashRouter
3.3.5 路由的严格匹配与模糊匹配
  1. 默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
  2. 开启严格匹配:<Route exact={true} path="/about" component={About}/>
  3. 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
3.3.6 Redirect的使用
  1. 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
  2. 具体编码:
<Switch>
	<Route path="/about" component={About}/>
	<Route path="/home" component={Home}/>
	<Redirect to="/about"/>
</Switch>
3.4 嵌套路由导航
  1. 在嵌套的组件里去写,但是一定要带上当前父组件的路由;注册子路由时要写上父路由的path值

  2. /home/news: 路由的匹配是按照注册路由的顺序进行的。 首先会一级一级的匹配,先匹配到home,那么会出现home组件;然后再进行匹配子级路由;前提是不能开启exact

  3. 编码如下:

    <div>
    	<ul className="nav nav-tabs">
    			<li>
    				<MyNavLink to="/home/news">News</MyNavLink>
    			</li>
    			<li>
    				<MyNavLink to="/home/message">Message</MyNavLink>
    			</li>
    		</ul>
    	{/* 注册路由 */}
    		<Switch>
    			<Route path="/home/news" component={News}/>
    			<Route path="/home/message" component={Message}/>
    			<Redirect to="/home/news"/>
    		</Switch>
    	</div>
    

3. 5 向路由组件传递参数

  1. params参数
    1. 路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
    2. 注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
    3. 接收参数:this.props.match.params
  2. search参数
    1. 路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
    2. 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
    3. 接收参数:this.props.location.search ;备注:获取到的search是urlencoded编码字符串,需要借助querystring解析(react脚手架创建项目的时候就下载了)
  3. state参数
    1. 路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
    2. 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
    3. 接收参数:this.props.location.state,备注:刷新也可以保留住参数(但是清除缓存就没有了)

3.6 编程式路由导航

场景: 图片如何跳转路由?或者是一个组件展示3s以后跳到其他地方

  1. 借助this.prosp.history对象上的API对操作路由跳转、前进、后退
    1. this.prosp.history.push()
    2. this.prosp.history.replace()
    3. this.prosp.history.goBack()
    4. this.prosp.history.goForward()
    5. this.prosp.history.go()
  2. 编码:
    replaceShow = (id,title)=>{
    	//replace跳转+携带params参数
    	//this.props.history.replace(`/home/message/detail/${id}/${title}`)
    
    	//replace跳转+携带search参数
    	// this.props.history.replace(`/home/message/detail?id=${id}&title=${title}`)
    
    	//replace跳转+携带state参数
    	this.props.history.replace(`/home/message/detail`,{id,title})
    }
    
    pushShow = (id,title)=>{
    	//push跳转+携带params参数
    	// this.props.history.push(`/home/message/detail/${id}/${title}`)
    
    	//push跳转+携带search参数
    	// this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)
    
    	//push跳转+携带state参数
    	this.props.history.push(`/home/message/detail`,{id,title})
    	
    }
    

3.7 withRouter的使用

  1. withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
  2. withRouter的返回值是一个新组件
  3. 使用
    1. import {withRouter} from 'react-router-dom'
    2. export default withRouter(Header)

3.8 BrowserRouter与HashRouter的区别

  1. 底层原理不一样:
    BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
    HashRouter使用的是URL的哈希值。
  2. path表现形式不一样
    BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
    HashRouter的路径包含#,例如:localhost:3000/#/demo/test
  3. 刷新后对路由state参数的影响
    (1).BrowserRouter没有任何影响,因为state保存在history对象中。
    (2).HashRouter刷新后会导致路由state参数的丢失,无法记录state!!!
  4. 备注:HashRouter可以用于解决一些路径错误相关的问题。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值