基本组件
React Router中有三种类型的组件:路由器组件,路由匹配组件和导航组件
路由器组件
对于Web项目,react-router-dom
提供<BrowserRouter>
和<HashRouter>
路由器。
两者区别:
– 地址栏: BrowserRouter
地址栏显示方式:http://localhost:8080/abc/def
,HashRouter
地址栏显示方式:http://localhost:8080/#/abc/def
– <BrowserRouter>
需要server
端的配合,每一次跳转页面都向服务器发送一次请求,服务器需要进行处理
– <HashRouter>
不会向服务器发起请求,会找到相对于的模块然后进行渲染
– 个人觉得如果是静态页面,使用<HashRouter>
就好
<BrowserRouter>
使用:
需要在服务器接受路由,然后返回文件(以node后台为例)
app.get('*',(request,response)=>{
response.sendFile(path.resolve(__dirname,'../index.html'))
})
<HashRouter>
使用:
import { HashRouter as Router, Route } from 'react-router-dom'
import Home from './views/home'
<Router>
<Route path='/' component={Home}/>
</Router>
路由匹配组件<Route>
和<Switch>
<Switch>
可对子元素<Route>
进行分组,并仅渲染与当前位置匹配的第一个元素
<Route>
如果匹配到对应的path
将会渲染对应组件,如果没有匹配到,则返回null
,如果不设置path
属性,将会一直渲染
使用:
import About from './views/about'
import Home from './views/home'
import Services from './views/services'
public render():JSX.Element {
return (
<Router>
<Switch>
{/* 当路由为 " / " 时 */}
{/* Home组件将会被渲染 */}
<Route path='/' component={Home}/>
{/* About不会渲染,返回null */}
<Route path='/about' component={About}/>
{/*上面都不匹配将会渲染Services组件 */}
<Route component={Services}/>
</Switch>
</Router>
)
}
渲染方式:component
,render
,和children
。
使用:
import About from './views/about'
import Home from './views/home'
import Services from './views/services'
const AboutCom = (props:any) => {
return (
<About />
)
}
class App extends React.Component {
public render():JSX.Element {
return (
<Router>
<Switch>
{/* 使用component渲染 */}
<Route path='/home' component={Home}/>
{/* 使用render渲染 */}
<Route path='/about'
render={AboutCom}/>
{/* 使用children渲染 */}
<Route children={AboutCom}/>
</Switch>
</Router>
)
}
}
<Link>
导航
这个组件主要用于导航,它将会找到相匹配的路由,然后进行渲染,以下为测试结果:
App.tsx
<Router>
<Switch>
<Route path='/' exact={true} component={Home} />
<Route path='/linkTest' component={LinkTest} />>
</Switch>
</Router>
Home.tsx
<div>
<p>这是首页</p>
<Link to='/linkTest'>点击这个Link跳转到Link组件</Link>
</div>
默认页面是Home,点击Home页面中Link跳转到LinkTest页面,因为这是在App.tsx中定义的,所以将会重新打开一个新的页面
<Redirect>
重定向
将导航到新的位置,且新位置会覆盖历史堆栈中的位置
<Router getUserConfirmation={getConfirmation}>
<Switch>
<Route path='/' exact={true} component={Home}/>
<Route path='/home' component={Home}/>
<Route path='/about'
render={AboutCom}/>
{/* 当地址为:ip::3000/#/anywhere都将跳转到Home页面 */}
<Redirect to='/'/>
</Switch>
</Router>
路径(path)
<Route path='/roster'/>
// 当路径名为'/'时, path不匹配
// 当路径名为'/roster'或'/roster/2'时, path匹配
// 当你只想匹配'/roster'时,你需要使用"exact"参数, 路由仅匹配'/roster'而不会匹配'/roster/2'
<Route exact={true} path='/roster'/>
嵌套路由
在以前的版本中可以使用以下:
<Route component={App}>
<Route path="/" components={Home} />
<Route path="users" components={Users}>
<Route path="users/:userId" component={Profile} />
</Route>
</Route>
但是在4.0版本之后就和之前的版本不一样了,详见;react-router官网
路由传参
- 配置路由
<Route path='/user/:id' component={User} />
- 跳转传参
- 1.传入
string
:<Link to={'/user/2'}>跳转传递字符串</Link>
- 2.传入
Object
:<Link to={{ pathname:'/user', search: '?sort=name',hash: '#the-hash',state: { fromDashboard: true }}}>跳转传递对象</Link>
- 1.传入
User
页面获取- 1.传入
string
时获取方式:this.props.match.params.id
- 2.传入
Object
时获取方式:this.props.location
- 1.传入
1.这里的
id
和路由中的/user/:id
一样,如果路由为/user/:userId
,则获取this.props.match.params.userId
;2.如果参数是对象,则存在this.props.location
中
异步加载方案
安装Loadable
yarn add react-loadable
简单封装一次
在router/index.tsx
引入使用:
import * as React from 'react'
import * as Loadable from 'react-loadable'
interface IRoute {
component: Promise<React.ComponentClass<any> | React.StatelessComponent<any> | { default: React.ComponentType<any> }>,
path: string
}
export const route:IRoute[] = [
{
component: import('../views/Support'),
path: '/support'
},
{
component: import('../views/About'),
path: '/about'
},
{
component: import('../views/Services'),
path: '/services'
}
]
function Loading(props: any) {
console.log(props)
if (props.error) {
return <div>Error!</div>
} else if (props.timedOut) {
return <div>Taking a long time...</div>
} else if (props.pastDelay) {
return <div>loading</div>
} else {
return <div>loading</div>
}
}
export const loadable = (component: Promise<React.ComponentClass<any> | React.StatelessComponent<any> | { default: React.ComponentType<any> }>) => {
return Loadable({
delay: 200,
loader: () => component,
loading: Loading,
timeout: 10000,
})
}
调用
在定义路由的地方调用:
import * as React from 'react'
import { Route, Switch } from 'react-router-dom'
import Nav from '../../component/nav'
import { loadable, route } from '../../routes'
interface IRouteItem {
component: Promise<React.ComponentClass<any> | React.StatelessComponent<any> | { default: React.ComponentType<any> }>,
path: string
}
export default class Home extends React.Component {
public render ():JSX.Element {
return (
<div>
<Nav />
<Switch>
{route.map((item:IRouteItem, index:number) => {
return (
<Route path={item.path} component={loadable(item.component)} key={index}/>
)
})}
</Switch>
</div>
)
}
}
Webpack配置Less css加载器
1.安装less相关依赖
这是不可逆的操作,它将
create-react-app
的配置反编译到当前项目,从而完全取得 webpack 文件的控制权,无法回到原来的项目版本!自己在使用的时候,它提示让我提交了代码再使用这命令,应该是想让我保存当前版本吧。-.-
yarn eject
这个命令详见:这里
2.安装less相关依赖
npm install less less-loader --save-dev
3.配置webpack.config.dev.js
和webpack.config.prod.js
文件(做相同配置)
- 找到
css-loader
所在位置 - 修改
css
的test
正则 为/\.(css|less)$/,
- 在use中添加
less-loader
{
loader: require.resolve('less-loader'),
options: {
importLoaders: 1
}
}
- 找到
exclude
,在末尾添加/\.(css|less)$/