React 学习笔记 04 React-Route路由
2019-04-13 本文已影响0人
Upcccz
fetch
js原生方法,用来替换XMLHttpRequest的,是基于Promise的,不兼容ie6,但是有一个插件whatwg-fetch来兼容ie(兼容到ie6,是封装XMLHttpRequest,让其有和fetch一样的API)
// fetch(url,config)
// 第一个参数 请求路径
// 第二个参数 请求配置选项:请求方法(默认是GET),请求参数,跨域模式,是否带cookie,请求头,超时时间
fetch('./data.json')
.then(res=>{ // 不同的是 只要服务器有响应就会触发 不管是成功还是失败
console.log('响应对象',res) // 不仅仅是响应的数据 还包含了响应头 响应体
// fetch 封装了4个类 Resquest , Response , Header, Body
// Resquest 请求实例 fetch('./data.json')
// Response 响应实例
// Body => 响应体类,提供了text() , json() ,blob(), arrayBuffer() ,formData()
// 用来将数据格式化成不同的类型然后返回一个Promise对象
var promise = res.text(); // 以字符串的形式获取响应结果
promise.then(data=>{
console.log('响应结果解析成功',data)
}).catch(err=>{
console.log('响应结果解析失败',err)
})
})
.catch(err=>{ // 类似服务器网络中断这种情况才会触发catch 就是服务器没有任何响应的时候 触发catch
console.log(err)
})
// 简化写法
fetch('./data.json')
.then(res=>res.json()) // 这里就是返回的就是上面的那个promise
.then(data=>{
console.log('响应结果解析成功',data)
}).catch(err=>{
console.log('响应结果解析失败',err)
})
// 配置选项
fetch('./data.json',{
mothod: 'post',
body: 'a=1&b=2'
headers : {
'Content-Type': 'application/x-www-form-urlencoded' // 表单类型键值对的请求
// 文件上传 'multipart/form-data'
},
mode:"no-cors", // 设置不支持cors跨域 默认是支持 一般不会设置这个选项
credentials: 'include' // 默认不发送 'same-origin' 同源才发送 'include'都发送cookie
})
react-route
基本使用
// 安装 4.x版本的 react-route-dom 是包含了核心库 react-route的
npm i react-route-dom -S
// import { Router } from 'react-route-dom'
// 这个Router是相当于是VueRouter的,负责包括所有的路由记录
// 但是本身是抽象的 不能直接使用 因为它不知道该使用哪种模式
// 它拥有四个子类:{BroswerRouter} {HashRouter} {StaticRouter} {MemoryRouter}
// BroswerRouter 对应 history模式
// HashRouter 对应 hash 模式
import { BrowserRouter as Router, Route } from 'react-router-dom'
class App extends React.Component {
render(){
return (
<Router>
<div>
{/* exact 精准拼配 Router必须有一个根元素*/}
<Route exact path="/" component={Home}/>
<Route path="/news" render={()=>(<h1>我是一个news组件</h1>)}/>
</div>
</Router>
)
}
}
ReactDOM.render(<App/>,document.getElementById('app'))
关于重定向
import { HashRouter as Router,Route,Redirect } from 'react-router-dom'
<Router>
<div>
<Route path="/goods" component={Goods}/>
<Redirect to="/home" from="/" /> {/* /重定向到首页 */}
</div>
</Router>
<Route exact path="/" render={() => (
loggedIn ? (<Redirect to="/dashboard"/>) : (<PublicHomePage/>)
)}/>
<Redirect
to={{
pathname: "/login",
search: "?utm=your+face",
state: { referrer: currentLocation }
}}
/>
<Redirect push to="/somewhere/else" />
// push 是一个bool值,使用push 而不是replace
关于Link 和 NavLink
import { HashRouter as Router,Route,Link, NavLink} from 'react-router-dom'
<Router>
<div>
{/* Link标签本质还是a便签 */}
<Link to="/home">首页</Link>
<Link to="/goods">商品</Link>
<hr/>
{/* 与route-link 差不多 会给激活的NavLink 添加一个active类 */}
<NavLink to="/home">首页</NavLink>
<hr/>
{/* 可以使用activeClassName自定义这个类名 一把使用第三方样式的时候使用 */}
<NavLink to="/home" activeClassName='myActive'>首页</NavLink>
<hr/>
{/* 也要加exact精准匹配 不然active类会在跳转到/home的时候 在两个NavLink标签上都加上 */}
<NavLink to="/" exact >Index</NavLink>
<NavLink to="/home">首页</NavLink>
<hr/>
<Route path="/goods" component={Goods}/>
{/* /重定向到首页 */}
<Redirect to="/home" from="/" />
</div>
</Router>
关于Switch组件
Switch组件让路由在匹配到第一个组件时就结束匹配
import { HashRouter as Router,Route,Switch} from 'react-router-dom'
<Router>
<div>
{/*Switch一定要加 不然有多少个路由 每次跳转的时候就会匹配多少次 影响性能*/}
<Switch>
{/*在Switch中 如果默认路径不加 exact 不管跳转哪里都会跳转到Index 因为'/xxx'都会匹配到'/' */}
{/* exact是bool值 可以设置为false。exact={false} 实现的是 url.pathname === Route的path属性 */}
<Route exact path="/" component={Index}/>
<Route path="/home" component={Home}/>
<Route path="/goods" component={Goods}/>
</Switch>
</div>
</Router>
嵌套路由
class App extends React.Component {
render(){
return (
<Router>
<Route path="/home" component={Home}/>
<Route path="/goods" component={Goods}/>
</Router>
)
}
}
class Goods extends React.Component {
render(){
return (
<Router>
{/* 必须要连接/goods 不然无法匹配 因为每次匹配都是从最外层开始 */}
{/* /goods 一定不能设置 exact 不然/goods/phone根本就匹配不到路由/goods 那Goods组件都不会渲染 更不会有子路由组件渲染的机会*/}
<Route path="/goods/phone" component={Phone}/>
<Route path="/goods/food" component={Food}/>
</Router>
)
}
}
动态路由
class App extends React.Component {
render(){
return (
<Router>
<Route path="/home" component={Home}/>
<Route path="/:myPath" component={Product}/>
</Router>
)
}
}
class Product extends React.Component {
render(){
return (
<Router>
{/* 必须要连接/goods 不然无法匹配 因为每次匹配都是从最外层开始 */}
{/* /goods 一定不能设置 exact 不然/goods/phone根本就匹配不到路由/goods 那Goods组件都不会渲染 更不会有子路由组件渲染的机会*/}
<Route path="/phone" component={Phone}/>
<Route path="/food" component={Food}/>
</Router>
)
}
componentDidMount(){ // 一般在这个钩子中请求数据 渲染视图
console.log(this.props)
// 动态路由的props上有三个属性 history location match
// history 历史对象== this.ptops.history.push() / this.ptops.history.replace() / goBack / go
// 编程式跳转
// location 当前地址信息对象 = 当前路由的hash pathname search(?a=1&b=2) state
// match 匹配对象 拥有isExact params(myPath:phone) path(/:myPath) url(/phone)
// 相当于this.$route.params.myPath
}
}
为什么要在componentDidMount
中获取数据:更新期4个钩子不能调用setState
所有创建周期的render
不行,然后componentWillMount
会被执行两次
动态路由需要在componentWillReceiveProps
获取数据,因为动态路由使用同一个组件,组件的componentDidMount
只会执行一次