尹君恋雪 發表於 2019-7-2 10:01:00

React router的Route应用

<style>p.p1 { margin: 0; font: 12px ".PingFang SC" }
span.s1 { font: 12px "Helvetica Neue" }</style>
<style>p.p1 { margin: 0; font: 12px "Helvetica Neue" }
p.p2 { margin: 0; font: 12px ".PingFang SC" }
p.p3 { margin: 0; font: 12px "Helvetica Neue"; min-height: 14px }
span.s1 { font: 12px ".PingFang SC" }
span.s2 { font: 12px "Helvetica Neue" }
span.Apple-tab-span { white-space: pre }</style>
<p>Route 是 React Router中用于配置路由信息的组件,每当有一个组件需要根据 URL 决定是否渲染时,就需要创建一个 Route。</p>
<p>react-router 中的很多特性都与 React 保持了一致,比如它的声明式组件、组件嵌套,当然也包括 React 的状态机特性。</p>
<h2>1.path</h2>
<p>每个Route都需要一个path属性,path属性是一个url,当URL匹配一个Route时,这个Route中定义的组件就会被渲染出来。</p>
<h2>2.Route渲染组间的方式</h2>
<p>(1)Component</p>
<p>component的值是一个组件,当URL和Route匹配时,Component属性定义的组件就会被渲染。</p>
<div class="cnblogs_code">
<pre>&lt;Route path="/mycom" component={MyCom} &gt;</pre>
</div>
<p>(2)Render</p>
<p>Render 值是一个函数,这个函数返回一个React元素。这种方式方便地为待渲染的组件传递额外的属性。</p>
<div class="cnblogs_code">
<pre>&lt;Route path=‘/mycom’render={(props) =&gt; {

&lt;MyCom {…props} data={extraProps} /&gt; <span style="color: rgba(153, 204, 0, 1)">//MyCom 组件接收了一个额外的<span class="s2">data属性</span></span>
<span style="color: rgba(0, 0, 0, 1)">
}}</span>&gt;

&lt;/Route&gt;</pre>
</div>
<p>(3)children</p>
<p>Children的值也是一个函数,函数返回要渲染的React元素。与前面不同是,无论是否匹配成功,children返回的组件都会被渲染。匹配不成功时,match属性为null。</p>
<div class="cnblogs_code">
<pre>&lt;Route path="/myCom" render={(props) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {

</span>&lt;div className={props.match ? 'active' : ''}&gt;

   &lt;Foo {…props} data={extraProps} /&gt;

&lt;/div&gt;
<span style="color: rgba(0, 0, 0, 1)">
}}

</span>&lt;/Route&gt;</pre>
</div>
<p class="p1"><span class="s1" style="font-size: 14px; font-family: &quot;Microsoft YaHei&quot;">如果Route<span class="s1">匹配当前URL<span class="s1">,待渲染元素的根节点div<span class="s1">的class<span class="s1">将设置成active.</span></span></span></span></span></p>
<h2>3.多级路由</h2>
<p>在路由里面继续写路由,挂载组件,就可以实现多级路由。路由嵌套实现。</p>
<div class="cnblogs_code">
<pre><span style="font-family: &quot;Microsoft YaHei&quot;">&lt;Route path=‘/myCom’ component={myCom}&gt;
  &lt;Route path=‘/myCom/sonCom’ component={SonCom}&gt;&lt;/Route&gt;
&lt;/Route&gt;</span></pre>
</div>
<p>如果多级路由嵌套的层次太深,那我们写子路由的path就会特别麻烦,所以可以这样:</p>
<div class="cnblogs_code">
<pre><span style="font-family: &quot;Microsoft YaHei&quot;">&lt;Route path=‘/mycom’render={(props) =&gt; {
  &lt;Route path={`${props.match.path}/sonCom`} component={SonCom} /&gt;<span style="color: rgba(0, 0, 0, 1)">
}}</span>&gt;
&lt;/Route&gt;</span></pre>
</div>
<p>Match是从props解构出来,match.path就是我们当前这个路由的路径,这样不管嵌套多深,都可以写上一级的路由</p>
<h2>4.动态传参</h2>
<p>/foodlist/:id,传过去的值就在路由挂载组件的props中,props里有个match, match中有个params,&nbsp;注意:props只在路由挂载的组件才有</p>
<p>&lt;Route path=‘/foodlist/:id’ component={MyCom} /&gt;</p>
<p>MyCom 组件的props中就可以获取到id</p>
<p>可以在一个组件中用 this.props.history.push(“/path”, {name: “hellow”}), 来进行传参,传过去的值在props.location.state中</p>
<h2>5.withRouter</h2>
<p>一个典型的高阶组件,如果我们既想实现点击跳转,又不想用Link的a标签,我们可以用withRouter给我们吐出来一个实现点击跳转路由的组件。 Eg.</p>
<div class="cnblogs_code">
<pre><span style="font-family: &quot;Microsoft YaHei&quot;">import { withRouter } from '<span style="color: rgba(0, 0, 0, 1)">react-router-dom’;

//使用自定义的组件:

&lt;CustomNavLink to="/food"&gt;food&lt;/CustomNavLink&gt;

&lt;CustomNavLink to="/wiki"&gt;wiki&lt;/CustomNavLink&gt;

&lt;CustomNavLink to="/profile"&gt;profile&lt;/CustomNavLink&gt;

//给自定义组件实现点击功能:

const CustomNavLink = withRouter(class EnhenceCustomNavLink extends Component {

    render () {

      return (

      &lt;li onClick={this.goto.bind(this)}&gt;

          {

            this.props.location.pathname === this.props.to ? </span>'&gt;'<span style="color: rgba(0, 0, 0, 1)"> + this.props.children : this.props.children

          }

      &lt;/li&gt;

      )

    }

    goto () {

      this.props.history.push(this.props.to)

    }

})</span></span></pre>
</div>
<p>假如你的组件没有路由信息,你可以使用withRouter(component)将这个组件包起来,props里面就有路由信息了。</p>
<p>&nbsp;</p>
<p><span style="color: rgba(255, 0, 0, 1)">这里我们顺便了解下前端路由的两种模式:Hash模式和History模式</span></p>
<h2>1、Hash 模式:</h2>
<p>&nbsp;这里的 hash 就是指 url 尾巴后的 # 号以及后面的字符。Hash 也称作锚点,用来做页面的定位,可以使对应的id的元素显示在可视区域内。</p>
<p>Hash值的变化不会导致浏览器向服务器发出请求,而且hash改变会触发hashchange事件,浏览器的前进和后退也能对其进行控制,在html5的history出现前,基本就是使用hash来实现前段路由的。</p>
<div class="cnblogs_code">
<pre>window.location.hsah = 'qq' <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置url的hash,会在当前url后加上#qq</span>

<span style="color: rgba(0, 0, 255, 1)">var</span> hash = window.location.hsah <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">qq</span><span style="color: rgba(0, 0, 0, 1)">

Window.addEventListener('hashchange', </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">监听hash变化,点击浏览器的前进后退会触发</span>
<span style="color: rgba(0, 0, 0, 1)">)</span></pre>
</div>
<p class="p2">&nbsp;</p>
<h2>2, History模式</h2>
<p>已经有 hash 模式了,而且 hash 能兼容到IE8, history 只能兼容到 IE10,为什么还要搞个 history 呢?</p>
<p>首先,hash 本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了。其次,hash 的传参是基于 url 的,如果要传递复杂的数据,会有体积的限制,而 history 模式不仅可以在url里放参数,还可以将数据存放在一个特定的对象中。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">window.history.pushState(state, title, url)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> state:需要保存的数据,这个数据在触发popstate事件时,可以在event.state里获取</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> title:标题,基本没用,一般传 null</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> url:设定新的历史记录的 url。新的 url 与当前 url 的 origin 必须是一樣的,否则会抛出错误。url可以是绝对路径,也可以是相对路径。</span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">如 当前url是 https://www.baidu.com/a/,执行history.pushState(null, null, './qq/'),则变成 https://www.baidu.com/a/qq/,执行history.pushState(null, null, '/qq/'),则变成 https://www.baidu.com/qq/ </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

window.history.replaceState(state, title, url)
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 与 pushState 基本相同,但这是修改当前历史记录,而 pushState 是创建新的历史记录</span>
<span style="color: rgba(0, 0, 0, 1)">
window.addEventListener(“popstate”, funbction(){
  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 监听浏览器前进后退事件,pushState 与 replaceState 方法不会触发   </span><span style="color: rgba(0, 0, 0, 1)">
});

window.history.back() </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 后退</span><span style="color: rgba(0, 0, 0, 1)">
window.history.forward()</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 前进</span><span style="color: rgba(0, 0, 0, 1)">
window.history.go(</span>1) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">前进一步,-2为后退两步,window.history.length可以查看当前历史堆栈中页面的数量</span></pre>
</div>
<p>history 模式改变 url 的方式会导致浏览器向服务器发送请求,需要在服务器端做处理:如果匹配不到任何静态资源,则应该始终返回同一个 html 页面。</p>
<p>&nbsp;</p>
<style>p.p1 { margin: 0; font: 12px ".PingFang SC" }
p.p2 { margin: 0; font: 12px "Helvetica Neue"; color: rgba(220, 161, 13, 1) }
p.p3 { margin: 0; font: 12px "Helvetica Neue" }
p.p4 { margin: 0; font: 12px "Helvetica Neue"; min-height: 14px }
p.p5 { margin: 0 0 0 23px; font: 12px "Helvetica Neue"; min-height: 14px }
li.li1 { margin: 0; font: 12px ".PingFang SC" }
span.s1 { font: 12px "Helvetica Neue" }
span.s2 { font: 12px ".PingFang SC" }
span.s3 { color: rgba(0, 0, 0, 1) }
span.s4 { font: 12px ".PingFang SC"; color: rgba(0, 0, 0, 1) }
span.s5 { text-decoration: underline; color: rgba(220, 161, 13, 1) }
span.Apple-tab-span { white-space: pre }
ol.ol1 { list-style-type: decimal }</style>
<p><span style="color: rgba(255, 0, 0, 1)">我们再顺便了解下:用户访问的URL后面加入# 号的知识</span></p>
<h2>1. #号的含义:</h2>
<p>#号代表网页中的一个位置,# 号后面的内容就是该位置的一个标记,eg.</p>
<div class="cnblogs_code">
<pre>http:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">www.example.com/index.html#print</span></pre>
</div>
<p>访问该地址,浏览器页面会自动滚动到print 位置,print显示在可视区域</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">为页面指定位置的有两种方式:</span>
<span style="color: rgba(0, 0, 0, 1)">
(</span>1)加锚点 &lt;a name=“print”&gt;&lt;/a&gt;
(2)&lt;div id=“print”&gt;&lt;/div&gt;</pre>
</div>
<h2>2.Http请求不包括#部分</h2>
<p>比如访问上面的链接,实际发出的请求是:</p>
<div class="cnblogs_code">
<pre>GET /index.html HTTP/1.1<span style="color: rgba(0, 0, 0, 1)">

Host: www.example.com</span></pre>
</div>
<p>#号后面的任何字符,都会被解析为位置标志符,比如:</p>
<div class="cnblogs_code">
<pre>http:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">www.example.com/?color=#fff</span></pre>
</div>
<p>实际发出的请求是:</p>
<div class="cnblogs_code">
<pre>GET /?color= HTTP/1.1<span style="color: rgba(0, 0, 0, 1)">
Host: www.example.com</span></pre>
</div>
<p>这并不是我们所期望的,可以对#号转义 #转为23%</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">http://www.example.com/?color=23%fff</pre>
</div>
<p class="p1">&nbsp;</p>
<h2>3.改变网页的#号部分,不会触发网页的重载</h2>
<div class="cnblogs_code">
<pre>http:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">www.example/com/index.html#location1</span>
http:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">www.example.com/index.html#location2 </span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">改变#号后面的内容,不会重新触发服务器的请求,也就是#号后面的内容对服务器端没影响</span></pre>
</div>
<h2>4.改变#号后面的内容,可以修改浏览器的访问历史</h2>
<p>每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"按钮,就可以回到上一个位置。</p>
<h2>5.window.location.hash 可以读到#号后面的内容</h2>
<p>来判断网页是否发生了变化,给window.location.hash赋值时,就是增加了一条浏览器的历史访问记录</p>
<h2>6. onhashchange 是HTML5增加的可以监听hash改变的接口:</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">window.onhashchange = func;
&lt;body onhashchange="func();"&gt;
window.addEventListener("hashchange", func, false);</pre>
</div>
<p>对于不支持onhashchange的浏览器,可以用setInterval监控location.hash的变化。</p>
<h2>7.Google抓取#的机制</h2>
<p>默认情况下,Google的网络蜘蛛忽视URL的#部分。</p>
<p>如果你希望Ajax生成的内容被浏览引擎读取,那么URL中可以使用"#!",Google会自动将其后面的内容转成查询字符串_escaped_fragment_的值。</p>
<p class="p5"><span style="font-size: 14px">&nbsp;</span></p>
<style>p.p1 { margin: 0; font: 12px ".PingFang SC" }
span.s1 { font: 12px "Helvetica Neue" }</style>
<p class="p1">&nbsp;</p>
<p class="p2">&nbsp;</p>
<style>p.p1 { margin: 0; font: 12px ".PingFang SC" }
span.s1 { font: 12px "Helvetica Neue" }</style>
<style>p.p1 { margin: 0; font: 12px "Helvetica Neue" }
p.p2 { margin: 0; font: 12px ".PingFang SC" }
p.p3 { margin: 0; font: 12px "Helvetica Neue"; min-height: 14px }
span.s1 { font: 12px ".PingFang SC" }
span.s2 { font: 12px "Helvetica Neue" }
span.Apple-tab-span { white-space: pre }</style>
<style>p.p1 { margin: 0; font: 12px ".PingFang SC" }
p.p2 { margin: 0; font: 12px "Helvetica Neue"; min-height: 14px }
p.p3 { margin: 0; font: 12px "Helvetica Neue" }
span.s1 { font: 12px "Helvetica Neue" }
span.s2 { font: 12px ".PingFang SC" }
span.Apple-tab-span { white-space: pre }</style><br><br>
来源:https://www.cnblogs.com/torri/p/11118754.html
頁: [1]
查看完整版本: React router的Route应用