原文连接https://blog.csdn.net/liangklfang/article/details/53355553javascript
上面的例子表示当页面的路由知足了特定的格式,我就会去实例化Standarz这个router Component,那么咱们看看实例化这个Router Component的时候会穿进去那些参数:html
下面我将会仔细分析一下上面的内容,不过以前我仍是想去看看Router这个Route Component自带的history参数。java
问题2:Router这个Component的history参数有那些可选择项react
browserHistory:表示使用浏览器默认的history API去检测路由的变化,这时候服务器端必须可以处理特定的路由而后响应给客户端;支持服务器端渲染;URI比较简洁
hashHistory:不须要服务器端支持;不支持服务器端渲染;若是应用经过push和replace来不断修改history,那么咱们能够存储‘地址状态’,其不会在新的地址中出现,就像咱们在HTML中经过post来提交数据同样。hash历史经过DOM API的window.location.hash = newHash来不断改变,所以不存在新的地方去存储地址状态。可是,咱们但愿全部的历史都可以经过‘地址状态’来存储,所以咱们为每个地址建立了一个独一无二的key,并且把key存储在sessionstorage中,当用户点击后退,前进的时候咱们能够有一种机制去从新加载新的‘地址状态’。所以,当你在一个超连接中不断点击的时候其后面的_k是不断变化的,形式为:_k=a7h1uf
createMemoryHistory:Memory history不会修改和读取地址栏的地址,这是咱们实现服务端渲染的方式,并且他对于测试和其余渲染环境,如React Native也是颇有用的。他和其余两种历史也是不同的,由于你必须建立一个Memory History,s使用下面这种方式就能够进行测试了:web
const history = createMemoryHistory(location)
若是你想要进一步个性化你的history选项,或者使用其余方式去加强你的history,你可使用useRouterHistory。注意:useRouterHistory已是使用history的useQueries ,useBasename加强过了的。浏览器
下面是使用了basename:服务器
下面是使用了useBeforeUnload加强:session
问题3:router还有一个routes属性表示的是什么react-router
也就是说,这时候咱们不是Route嵌套在Router里面,而是做为Router的一个属性来传递,这也是能够的!若是发生了上面的路由嵌套,如加载/repos就会先加载APP,而后加载Repos,这时候咱们的APP必须经过this.props.children来实例化被嵌套组件:app
问题4:咱们先来研究上面那张图的params属性
咱们看看上面的路由配置:
<Route path="/stdize(/:name)" component={Standarz}>
咱们来详细的看看下面的params的签名:
也就是说,当咱们实例化Standarz的时候,能够经过params来获取到咱们传入的参数,全部参数所有封装在params对象上,以下:
注意:若是遇到了通配符的时候,咱们也是能够经过上面这种方式来取出数据:
并且这时候咱们访问/about/me/的时候,第二个组件不会被初始化,由于第一个路由也被匹配了,因此下一个就被直接跳过了!这时候params对象上有userName和id两个属性!
通配符的规则以下:
(1):paramName
:paramName匹配URL的一个部分,直到遇到下一个/、?、#为止。这个路径参数能够经过this.props.params.paramName取出。
(2)()
()表示URL的这个部分是可选的。
(3)*
*匹配任意字符,直到模式里面的下一个字符为止。匹配方式是非贪婪模式。
(4) **
** 匹配任意字符,直到下一个/、?、#为止。匹配方式是贪婪模式。
问题5:上面的route是什么?
从该图能够看出,其中传入的route属性有一个path属性表示的是路径,也就是咱们在Route中配置的path属性,还有一个component属性表示的Connect函数!
问题6:上面的routeParams属性是什么?
从输出能够看到,其和params是同样的签名
问题7:routes显示的是什么?
问题8:location指的是?
注意:这里的key就是上面说的‘地址状态’,若是访问地址为:http://localhost:8000/#/stdize/button?name=gssdy&_k=0zazfn,此时咱们的query就是对象:{name:'gssdy'},而咱们的search就是"?name=gssdy"。 location 对象,它能够简单的认为是 URL 的对象形式表示,这里要提的是 location.state,这里 state 的含义与 HTML5 的history.pushState API 中的 state 对象同样。每一个 URL 都会对应一个 state 对象,你能够在对象里存储数据,但这个数据却不会出如今 URL 中。实际上,数据被存在了 sessionStorage 中;
问题9:history的内部签名是?
其内部提供了不少的方法,方法列表如上。
9.1 history.pushState({name:'Nicholas'},'Nicholas Page','1.html')
执行pushState后,新的状态信息会被加入历史栈中,而浏览器地址栏也会变成新的相对URL,可是浏览器不会真正向服务器发送信息,即便状态改变以后从新查询location.href也会返回和地址栏中相同的地址。第二个参数目前没有浏览器实现,所以彻底尅传入一个空字符串,或者一个短标题。而第一个参数应该竟可能提供页面初始化所须要的各类信息,由于pushState会提供新的历史状态,你会发现后退按钮也可以用了!按下后退按钮会触发window的popstate事件,其含有一个state属性就是咱们第一个参数传入的属性。记住:浏览器加载的第一个页面没有状态,所以点击后退按钮返回浏览器加载的第一个页面时候state为null.
9.2 history.replaceState(null,'Nicholas Page','1.html')或者忽略第二个参数
更新当前状态,传入的参数和pushState前两个参数相同,调用这个方法不会再历史栈中建立新的状态,只会重写当前状态。
事实上,history/location两个对象同时存在于路由组件的 context 中,你还能够经过 React 的 context API 在组件的子级组件中获取到这两个对象。好比在 SignIn 组件的内部又包含了一个 SignInChild 组件,你就能够在组件内部经过 this.context.history 获取到 history 对象,进而调用它的 API 进行跳转等操做,这部份内容能够参考参考文献。
问题10:IndexRoute会默认加载一个组件,那么他是如何完成的?
上面代码中,访问根路径/,不会加载任何子组件。也就是说,App组件的this.props.children,这时是undefined。所以,一般会采用{this.props.children||<Home/>}这样的写法。这时,Home明明是Accounts和Statements的同级组件,却没有写在Route中。IndexRoute就是解决这个问题,显式指定Home是根路由的子组件,即指定默认状况下加载的子组件。你能够把IndexRoute想象成某个路径的index.html。
如今,用户访问/的时候,加载的组件结构以下。
这种组件结构就很清晰了:App只包含下级组件的共有元素,自己的展现内容则由Home组件定义。这样有利于代码分离,也有利于使用React Router提供的各类API。注意,IndexRoute组件没有路径参数path。
问题11:React-Router中还须要哪些注意点
(1)Redirect 组件,具备from和to两个参数,to表示的是绝对路径
(2)IndexRedirect组件表示访问跟路由的时候实例化的组件
(3)Link组件是a标签的React版本,具备activeStyle和activeClassName为当前路由指定样式
(4)连接到跟路由/应该使用IndexLink组件,而不是Link组件,由于跟路由activeStyle和activeClassName会失效,或者说老是生效,由于/会匹配任何子路由。而IndexLink组件会使用路径的精确匹配。固然也可使用Link组件的onlyActiveOnIndex属性
(5)若是使用表单跳转而不是用户点击跳转,可使用browserHistory.push:
或者使用context:
(6)路由的onEnter和onLeave钩子,可使用onEnter替代Redirect组件或者作一些认证:
也能够经过setRouteLeaveHook为一个特定的Route的指定离开的函数,以下:
问题1:首先看看本身页面中使用的一个react-router
上面的例子表示当页面的路由知足了特定的格式,我就会去实例化Standarz这个router Component,那么咱们看看实例化这个Router Component的时候会穿进去那些参数:
下面我将会仔细分析一下上面的内容,不过以前我仍是想去看看Router这个Route Component自带的history参数。
问题2:Router这个Component的history参数有那些可选择项
browserHistory:表示使用浏览器默认的history API去检测路由的变化,这时候服务器端必须可以处理特定的路由而后响应给客户端;支持服务器端渲染;URI比较简洁
hashHistory:不须要服务器端支持;不支持服务器端渲染;若是应用经过push和replace来不断修改history,那么咱们能够存储‘地址状态’,其不会在新的地址中出现,就像咱们在HTML中经过post来提交数据同样。hash历史经过DOM API的window.location.hash = newHash来不断改变,所以不存在新的地方去存储地址状态。可是,咱们但愿全部的历史都可以经过‘地址状态’来存储,所以咱们为每个地址建立了一个独一无二的key,并且把key存储在sessionstorage中,当用户点击后退,前进的时候咱们能够有一种机制去从新加载新的‘地址状态’。所以,当你在一个超连接中不断点击的时候其后面的_k是不断变化的,形式为:_k=a7h1uf
createMemoryHistory:Memory history不会修改和读取地址栏的地址,这是咱们实现服务端渲染的方式,并且他对于测试和其余渲染环境,如React Native也是颇有用的。他和其余两种历史也是不同的,由于你必须建立一个Memory History,s使用下面这种方式就能够进行测试了:
const history = createMemoryHistory(location)
若是你想要进一步个性化你的history选项,或者使用其余方式去加强你的history,你可使用useRouterHistory。注意:useRouterHistory已是使用history的useQueries ,useBasename加强过了的。
下面是使用了basename:
下面是使用了useBeforeUnload加强:
问题3:router还有一个routes属性表示的是什么
也就是说,这时候咱们不是Route嵌套在Router里面,而是做为Router的一个属性来传递,这也是能够的!若是发生了上面的路由嵌套,如加载/repos就会先加载APP,而后加载Repos,这时候咱们的APP必须经过this.props.children来实例化被嵌套组件:
问题4:咱们先来研究上面那张图的params属性
咱们看看上面的路由配置:
<Route path="/stdize(/:name)" component={Standarz}>
咱们来详细的看看下面的params的签名:
也就是说,当咱们实例化Standarz的时候,能够经过params来获取到咱们传入的参数,全部参数所有封装在params对象上,以下:
注意:若是遇到了通配符的时候,咱们也是能够经过上面这种方式来取出数据:
并且这时候咱们访问/about/me/的时候,第二个组件不会被初始化,由于第一个路由也被匹配了,因此下一个就被直接跳过了!这时候params对象上有userName和id两个属性!
通配符的规则以下:
(1):paramName
:paramName匹配URL的一个部分,直到遇到下一个/、?、#为止。这个路径参数能够经过this.props.params.paramName取出。
(2)()
()表示URL的这个部分是可选的。
(3)*
*匹配任意字符,直到模式里面的下一个字符为止。匹配方式是非贪婪模式。
(4) **
** 匹配任意字符,直到下一个/、?、#为止。匹配方式是贪婪模式。
问题5:上面的route是什么?
从该图能够看出,其中传入的route属性有一个path属性表示的是路径,也就是咱们在Route中配置的path属性,还有一个component属性表示的Connect函数!
问题6:上面的routeParams属性是什么?
从输出能够看到,其和params是同样的签名
问题7:routes显示的是什么?
问题8:location指的是?
注意:这里的key就是上面说的‘地址状态’,若是访问地址为:http://localhost:8000/#/stdize/button?name=gssdy&_k=0zazfn,此时咱们的query就是对象:{name:'gssdy'},而咱们的search就是"?name=gssdy"。 location 对象,它能够简单的认为是 URL 的对象形式表示,这里要提的是 location.state,这里 state 的含义与 HTML5 的history.pushState API 中的 state 对象同样。每一个 URL 都会对应一个 state 对象,你能够在对象里存储数据,但这个数据却不会出如今 URL 中。实际上,数据被存在了 sessionStorage 中;
问题9:history的内部签名是?
其内部提供了不少的方法,方法列表如上。
9.1 history.pushState({name:'Nicholas'},'Nicholas Page','1.html')
执行pushState后,新的状态信息会被加入历史栈中,而浏览器地址栏也会变成新的相对URL,可是浏览器不会真正向服务器发送信息,即便状态改变以后从新查询location.href也会返回和地址栏中相同的地址。第二个参数目前没有浏览器实现,所以彻底尅传入一个空字符串,或者一个短标题。而第一个参数应该竟可能提供页面初始化所须要的各类信息,由于pushState会提供新的历史状态,你会发现后退按钮也可以用了!按下后退按钮会触发window的popstate事件,其含有一个state属性就是咱们第一个参数传入的属性。记住:浏览器加载的第一个页面没有状态,所以点击后退按钮返回浏览器加载的第一个页面时候state为null.
9.2 history.replaceState(null,'Nicholas Page','1.html')或者忽略第二个参数
更新当前状态,传入的参数和pushState前两个参数相同,调用这个方法不会再历史栈中建立新的状态,只会重写当前状态。
事实上,history/location两个对象同时存在于路由组件的 context 中,你还能够经过 React 的 context API 在组件的子级组件中获取到这两个对象。好比在 SignIn 组件的内部又包含了一个 SignInChild 组件,你就能够在组件内部经过 this.context.history 获取到 history 对象,进而调用它的 API 进行跳转等操做,这部份内容能够参考参考文献。
问题10:IndexRoute会默认加载一个组件,那么他是如何完成的?
上面代码中,访问根路径/,不会加载任何子组件。也就是说,App组件的this.props.children,这时是undefined。所以,一般会采用{this.props.children||<Home/>}这样的写法。这时,Home明明是Accounts和Statements的同级组件,却没有写在Route中。IndexRoute就是解决这个问题,显式指定Home是根路由的子组件,即指定默认状况下加载的子组件。你能够把IndexRoute想象成某个路径的index.html。
如今,用户访问/的时候,加载的组件结构以下。
这种组件结构就很清晰了:App只包含下级组件的共有元素,自己的展现内容则由Home组件定义。这样有利于代码分离,也有利于使用React Router提供的各类API。注意,IndexRoute组件没有路径参数path。
问题11:React-Router中还须要哪些注意点
(1)Redirect 组件,具备from和to两个参数,to表示的是绝对路径
(2)IndexRedirect组件表示访问跟路由的时候实例化的组件
(3)Link组件是a标签的React版本,具备activeStyle和activeClassName为当前路由指定样式
(4)连接到跟路由/应该使用IndexLink组件,而不是Link组件,由于跟路由activeStyle和activeClassName会失效,或者说老是生效,由于/会匹配任何子路由。而IndexLink组件会使用路径的精确匹配。固然也可使用Link组件的onlyActiveOnIndex属性
(5)若是使用表单跳转而不是用户点击跳转,可使用browserHistory.push:
或者使用context:
(6)路由的onEnter和onLeave钩子,可使用onEnter替代Redirect组件或者作一些认证:
也能够经过setRouteLeaveHook为一个特定的Route的指定离开的函数,以下:
这部份内容能够阅读参考文献“React Router使用教程”