跳过
56-64 todo_list案例
67-70 github搜索案例
71 引入pubsub(订阅发布)用于任意组件间通信
94-96 antd
问题
onclick, bind, 箭头函数
oclick, 传递参数
参考
脚手架配置代理
方法一
在package.json中追加如下配置
"proxy": "http://localhost:5000"
说明:
- 优点:配置简单,前端请求资源时可以不加任何前缀。
- 缺点:不能配置多个代理。
- 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)
方法二
- 第一步:创建代理配置文件
在src下创建配置文件:src/setupProxy.js
- 编写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': ''}
})
)
}
说明:
- 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
- 缺点:配置繁琐,前端请求资源时必须加前缀。
fetch 发送请求
fetch(`/api1/search/users2?q=${keyWord}`)
.then(
response => {
console.log('联系服务器成功了');
return response.json()
},
error => {
console.log('联系服务器失败了',error);
return new Promise(()=>{}) // 用于中断 promise 链
}
)
.then(
response => {console.log('获取数据成功了',response);},
error => {console.log('获取数据失败了',error);}
)
try {
const response= await fetch(`/api1/search/users2?q=${keyWord}`)
const data = await response.json()
console.log(data);
PubSub.publish('atguigu',{isLoading:false,users:data.items})
}
catch (error) {
console.log('请求出错',error);
PubSub.publish('atguigu',{isLoading:false,err:error.message})
}
组件通信
父=>子:props。
子=>父:通过 props 父给子传递一个函数。
任意组件:pubsub.js
路由原理
Html5推出的history可以监听到路径变化,还可以直接修改路径同时让页面不跳转。
<a href="http://www.atguigu.com" onclick="return push('/test1') ">push test1</a>
<script type="text/javascript" src="https://cdn.bootcss.com/history/4.7.2/history.js"></script>
let history = History.createBrowserHistory()
function push (path) {
history.push(path)
return false
}
history.listen((location) => {
console.log('请求路由路径变化了', location)
})
路由的基本使用
1.明确好界面中的导航区、展示区
2.导航区的a标签改为Link标签
<Link to="/xxxxx">Demo</Link>
3.展示区写Route标签进行路径的匹配
<Route path='/xxxx' component={Demo}/>
4.<Link> 和 <Route> 外侧需要包裹 <BrowserRouter> 或 <HashRouter>,也可以包裹在 <App> 的外侧。
路由组件与一般组件
路由组件指写在 <Route> 中的组件。
一般组件:<Demo/>
路由组件:<Route path="/demo" component={Demo}/>
路由组件的 props 会接收到三个固定的属性:history, location, match。
通常把路由组件放在 pages 文件夹中,一般组件放入 components 文件夹中。
NavLink的使用
自带一个属性 activeClassName,用于指定选中时的样式。
封装NavLink
对任意标签,标签体内容等价于标签属性 children。可以通过 this.props.children 获取标签体内容。
<NavLink to="/about">About</NavLink>
// 等价于
<NavLink to="/about" children="About" />
Switch的使用
Switch可以提高路由匹配效率(单一匹配)。
解决多级路径刷新页面样式丢失的问题
因为 HTML 中引入 css 使用了相对路径导致的。
<link rel="stylesheet" href="./css/bootstrap.css">
多级路径导致 . 表示的相对路径发生了变化,所以没能获取到正确的样式。
<MyNavLink to="/atguigu/about">About</MyNavLink>
严格匹配与模糊匹配
默认是模糊匹配,即 to="/home/a/b" 可以匹配 path="/home",使用 exact 开启严格匹配。
<Route exact={true} path="/about" component={About} />
Redirect的使用
一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由。
<Redirect to="/about"/>
嵌套路由
路由的匹配是按照注册路由的顺序进行的。
向路由组件传递参数
-
params参数
路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
接收参数:this.props.match.params -
search参数
路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.search
备注:获取到的 search 是 urlencoded 编码字符串,需要借助 querystring 解析
import qs from 'querystring';
const { search } = this.props.location;
const { id, title } = qs.parse(search.slice(1));
- state参数
路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.state
备注:刷新也可以保留住参数。state 实际存放在 history 身上。
push 与 replace 模式
<MyNavLink replace to="/home/news">News</MyNavLink>
编程式路由导航
借助this.props.history对象上的API对操作路由跳转、前进、后退
this.props.history.push()
this.props.history.replace()
this.props.history.goBack()
this.props.history.goForward()
this.props.history.go()
withRouter的使用
withRouter可以加工一般组件(例如非页面的组件),让一般组件具备路由组件所特有的API,如 this.props.history 等。
(对于 vue 则不存在此问题,因为 vue 中一般组件也带了这些API)
BrowserRouter 与 HashRouter 的区别
和 vue 相同的地方不再赘述。=> 路由器的两种工作模式
因为state保存在history对象中,所以 HashRouter 刷新后会导致路由 state 参数的丢失。