zoukankan      html  css  js  c++  java
  • React Router

    路由可以向应用中快速的添加视图和数据流,同时保持页面与URL同步

    import {Router ,Route, Link} from 'react-router'
    
    class App extends React.Component {
            render(){
                 return (
                    <div>
                        <ul >
                            <li><Link to='/about'>About</Link></li>
                            <li><Link to='/inbox'>Inbox</Link></li>
                        </ul>
                        {this.props.children}
                    </div>
                    )}})
    //获取URL参数
    class Message extends React.Component{
        componentDidMount(){
          const id = this.props.params.id //来自于路径 ‘/inbox/messages/:id'
          
          fetchMessage(id,function(err,message){
            this.setState({message:message})
          })
      }
      render(){
        return(
          <div>
              <h3>message{this.props.params.id}</h3>
          </div>

    }

    React.render((
    <Router> <Route path='/' component={App}> <Route path='about' component={About} /> <Route path='inbox' component={Inbox} onEnter={requireAuth}>
                      <Route path='messages/:id component={Message} />
                  </Route>
    </Route> <Router> ).document.body);

    以上获取URL参数方法:

    1 id = this.props.params.id        来自父组件路径path=‘/index/message.:id'

    2 baz= this.props.location.query.bar   访问路径为  /foo?bar=baz 时,获取baz的值

    3 newhash = window.location.hash 简单的用于跳转,不用存储location state

    添加首页:IndexRouter 设置默认页面,当App的render中this.props.children还是undefined时显示

    <IndexRoute component={Dashboard}/>

    IndexLink

    如果使用<Link to='/'>Home</Link>,他会一直处于激活状态,因为所有的URL开头都是‘/'。而我们希望仅仅在home被渲染之后才激活并链接它。  可以使用<IndexLink to='/'>home</IndexLink>.

    简洁的URL:使用绝对路径,无需在URL中添加更多的层级,从而可以使用更简洁

    <Route path='/messages/:id' component={Message}/>  但其可能在动态路由中无法使用

    重定向Redirect 

    <Redirect from='message/:id' to='/message/:id'/>

    当有人点击/inbox/message/5时,会跳到/message/5,以防/inbox/message/5不存在

    onEnter和onLeave进入和离开的hook,在页面跳转确认时触发。例如 权限验证,或数据持久保存

    onLeave hook 在所有将离开的路由中触发,从最下层的字路由开始到最外层的父路由结束。

    onEnter hook从最外层的父路由开始到最下层的字路由结束

    例如:从/messages/5跳到/about,hook的执行顺序:/messages/:id的onLeave->/inbox的onLeave->/about的onEnter

    requireAuth(nextState,replace,callback){if(isLogined){replace('./home');}else{replace('./login');}callback();}

    路径语法

    :paramName 匹配位于/ ? # 之后的URL;称作参数

    () 在其内部的内容是可选的

    * 匹配任意字符

    History

    一个history知道如何去监听浏览器地址栏的变化,并解析这个url转化为location对象,然后router使用它匹配到路由,渲染对应的组件。

    1  browserHistory   

    使用浏览器中的 historyAPI 用于处理URL,创建 example.com/some/path这样的真实URL 

    2  hashHistory

    我使用URL中的hash#部分去创建形如 example.com/#/some/path的路由.window.location.hash = newhash

    3 creactMemoryHistory

    Memory history 不会在地址栏被操作或读取,非常适合测试和其他渲染环境。但必须创建

    const history = createMemoryHistory(location)

    高级进阶

    动态路由:

    根据‘按需加载’的原则,路由非常适合做代码拆分:他的责任就是配置好每个view。

    react router 的 路径匹配 及 组件加载 都是异步完成的,不仅允许你延迟加载组件,也可以延迟加载 路由的配置。在首次加载包中只需要有一个路径定义,路由会自动解析剩下的路径。

    route定义的函数 getChildRoutes、getIndexRoute、getComponents  都为异步加载‘逐渐匹配’

    const CourseRoute = {
    path:'cource/:id',
    
    getChildRoutes(location,callback){
        require.ensure([],function(require){
            callback(null,[
                require('./routes/Announcements'),
                require('./routes/Assignments'),
                require('./routes/Grades'),
              ])})},
    
    getIndexRoute(location,callback){
            require.ensure([],function(require){
                callback(null,require('./components/Index'))
            })}}
    
    getComponents(location,callback){
            require.ensure([],function(require){
                callback(null,require('./components/Course'))})}}

    跳转前确认:React Route 提供一个routerWillLeave的生命周期钩子,使得react组件可以拦截正在发生的跳转,或在离开route前提示用户。

    routerWillLeave 返回值有以下两种:

    1  return false 取消此次跳转

    2  return 返回提示信息,在离开route前提示用户进行确认。

    使用:1在route组件中引入 lifecycle mixin来安装这个钩子

    import { Lifecycle } from 'react-router'
    
    const Home = React.creactClass({
    
        //假设Home是一个 route 组件,使用 Lifecycle mixin 去获取一个 routerWillLeave 方法。
    
        mixins:[Lifecycle],
        
        routerWillLeave(nextLocation){
            if(!this.state.isSaved)
                return 'Your work is not saved! Are you sure leave?'
        },
    
        .....
    })

    2 如果想在一个深层次嵌套的组件中使用 routerWillLeave 钩子,只需在route组件中引入RouteContext mixin,这样就会把route放到context中。

    import { Lifecycle, RouteContext } from 'react-router'
    
    const Home  = React.creactClass ({
    
            //route 会被放在Home 和它子组件及孙子组件的context中,这样在层级树中Home及其所有子组件都可以拿到 route。
    
            mixin: [ RouteContext ],
    
            render(){
                return <NestedForm />
            } })
    
    const NestedForm = React.creactClass({
             //后代组件使用Lifecycle mixin 获得 一个routerWillLeave 的方法。
            mixins:[Lifecycle],
    
            routerWillLeave(nextLocation){
                if(!this.state.isSave)
                return 'your work is not saved !'
            },
            ......
    })

    服务端渲染:

    需求:放生错误时返回500, 需要重定向时返回30x,在渲染之前获得数据router

    方法:在<Router>API下一层使用:

    1 使用 match 在渲染之前根据 location 匹配route

    2 使用 RoutingContext 同步渲染 route 组件

    import { renderToString } from 'react-dom/server'
    import { match,RoutingContext } from 'react-router'
    import routes from './routes'
    
    serve((req,res) => {
    
         //这里的req.url应该是从初识请求中获得的
        //完整的URL路径,包括查询字符串
    
        match({routes,location:req.url},{error,redirectLocation,renderProps) => {
        if(error){
            res.send(500,error.message)
            }else if (redirectLocation){
            res.redirect(302,redirectLocation.pathname + redirectLocation.search
            }else if (renderProps){
            res.send(200,renderToString(<RoutingContext {...renderProps}   //renderProps可以构建任何想要的形势
            }else{
            res.send(404,'Not found')
            }})})

    路由组件的生命周期中获取数据:最简单的方法是通过router组件的生命周期Hook来实现。

    理解当路由改变时组件生命周期的变化,可以在Invoice组件里实现一个简单的数据获取功能

    let Invoice = React.creactClass({
    
        getInitialState(){
            return {
                invoice:null
            }
         },
    
        componentDidMount(){
            //初始化数据
            this.fetchInvoice()
        },
    
        componentDidUpdate(prevProps){
            //通过参数更新数据
            let oldId = prevProps.params.invoiceId
            let newId = this.props.params.invoiceId
            if (newId !== oldId)
                this.fetchInvoice()
            },
    
        componentWillUnmount(){
            //在组件移除前 忽略正在进行中的请求
            this.ignoreLastFetch = true
            },
    
        fetchInvoice(){
            let url = '/api/invoices/${this.props.params.invoiceId}
            this.request = fetch(url,(err,data) => {
                if (!this.ignoreLastFetch)
                    this.setState({invoice:data.invoice})
                })
    },
    
    render(){
            return <InvoiceView invoice = {this.state.invoice}/>
            }
    })

    组件外部跳转:

    在组件内部使用this.context.router来实现导航;

    在组件外部使用Router组件上被赋予的history可以实现导航。

    //main file 里renders a Router
    import { Router,browserHistory } from 'react-router'
    import routes from './app/routes'
    
    render(<Router history={browserHistory} routers={routes} />.el)
    
    
    //  a redux/flux action file:
    import { browserHistory } from 'react-router'
    browserHistory.push('/some/path')

    浏览器的前进后退按钮发生了什么????

    web浏览器的历史记录相当于一个仅有入栈的栈,当用户浏览器到某一个页面时将该文档存入到栈中,点击「后退」或「前进」按钮时移动指针到 history 栈中对应的某一个文档。

    • 使用 hashchange 事件来监听 window.location.hash 的变化
    • hash 发生变化浏览器会更新 URL,并且在 history 栈中产生一条记录
    • 路由系统会将所有的路由信息都保存到 location.hash 中
    • 在 react-router 内部注册了 window.addEventListener('hashchange', listener, false) 事件监听器
    • listener 内部可以通过 hash fragment 获取到当前 URL 对应的 location 对象

      在react中监听路由hash改变,包括 浏览器前进回退按钮 :componentWillReceiveProps(nextProps){if(nextProps.location.pathname != this.props.location.pathname){window.addEventListener('hashchange',listener,false)};

    点击Link后 路由系统发生????

    它的 to、query、hash 属性会被组合在一起并渲染为 href 属性。然后调用history.pushState(state,path) ,

    然后调用 window.location.hash 或者 window.history.pushState() 修改了应用的 URL

  • 相关阅读:
    高地址,低地址:
    大小端
    大小端
    linux下C语言编程解决warning : incompatible implicit declaration of built-in function问题
    给char赋16进制
    go channel 概述
    vue2.x入门学习
    vue-cli安装记录
    maven常用Java配置
    activiti工作流引擎
  • 原文地址:https://www.cnblogs.com/yxiaoqian/p/6132145.html
Copyright © 2011-2022 走看看