React Router 4.0 ---- 嵌套路由和動態路由
嵌套路由,從廣義上來說,分為兩種情況:一種是每個路由到的組件都有共有的內容,這時把共有的內容抽離成一個組件,變化的內容也是一個組件,兩種組件組合嵌套,形成一個新的組件。另一種是子路由,路由到的組件內部還有路由。
對於共有的內容,典型的代表就是網頁的側邊欄,假設側邊欄在左邊,我們點擊其中的按鈕時,右側的內容會變化,但不管右側的內容怎麽變化,左側的側邊欄始終存在。這個側邊欄就是共有內容,如下圖所示
這個共有內容要怎麽處理? 首先想到的就是把這個功能提取出來,寫成一個組件,然後再把這個組件依次應用到其它路由組件,如about, products 等。導航欄肯定是一個導航,不過這裏我們要使用navLink 組件,因為從圖片中可以看到它有高亮顯示,我們要設計一個高亮顯示的樣式。新建一個menus.js 文件,來寫這個導航組件
import React from ‘react‘ // 引入NavLink 組件 import { NavLink } from "react-router-dom"; import ‘./menus.css‘ // 高亮的樣式,表示我們在哪個導航下 const selectedStyle = { backgroundColor: ‘white‘, color: ‘slategray‘ } // navLink, activeStyle 點擊高亮顯示當前標簽。 export const MainMenu = () => ( <nav className=‘main-menu‘> <NavLink to=‘/‘>首頁</NavLink> <NavLink to=‘/about‘ activeStyle = {selectedStyle}>關於我們</NavLink> <NavLink to=‘/events‘ activeStyle = {selectedStyle}>企業事件</NavLink> <NavLink to=‘/products‘ activeStyle = {selectedStyle}>公司產品</NavLink> <NavLink to=‘/contact‘ activeStyle = {selectedStyle}>聯系我們</NavLink> </nav> )
可以看到導航的高亮樣式可以在NavLink 組件中直接設置,這也是Link 和NavLink的區別。這裏還寫了一點樣式,在menus.css 文件中。
/* 頁面左側主要導航 */ .main-menu { display: flex; flex-direction: column; height: 100%; width: 20%; min-width: 20%; background-color: slategray; color: ghostwhite; } .main-menu a { color: ghostwhite; text-align: center; padding: 1em; font-size: 1.5em; }
按照上面的說法,我們把這個組件應用到其它組件中,在pages.js中引入該組件,並修改Events,Products,
Contact和 About 組件中,引入的組件命名為MainMenu// 企業事件內容 export const Events = () => ( <div> <MainMenu></MainMenu> <section className="events"> <h1>企業大事件</h1> </section> </div> ) // 公司產品 export const Products = () => ( <div> <MainMenu></MainMenu> <section className="products"> <h1>公司產品:主要經營 手機、電腦</h1> </section> </div> ) // 聯系我們 export const Contact = () => ( <div> <MainMenu></MainMenu> <section className="contact"> <h1>聯系我們</h1> <p>公司電話:0755 - 12345678</p> </section> </div> )
這時你會發現,相同的代碼復制了4遍,還可以接受,畢竟只有一個共有組件。但如果about, home 這些組件有好多共有的部分,我們這樣一遍一遍的復制就有點麻煩了。所以還要對page.js文件這些組件相同的內容進行進一步的抽取。抽取的形式應該是
<div>
<MainMenu></MainMenu>
// 變化的部分
</div>
現在最主要的部分就是這些變化的部分要怎麽處理,想到了其實也很簡單,因為React 有一個children 屬性, 直接把這些變化的部分寫成props.childern 就可以了。這時你會發現,這個抽取的組件像一個布局模板, 比如單頁面應用時的頁眉和頁腳這些共有的部分,也可以放到這個模版中。新建一個template.js 文件
import React from ‘react‘ import { MainMenu } from "./menus"; export const Template = (props) => ( <div className = ‘page‘> <MainMenu></MainMenu> {props.children} </div> )
上面的代碼中加了一個樣式類page, 在pages.css 中添加一個 page樣式,
.page { display: flex; justify-content: space-between; height: 100%; margin-top: 20px; }
現在再在pages.js中的相應組件中應用Template組件
import { Template } from "./template";// 企業事件內容 export const Events = () => ( <Template> <section className="events"> <h1>企業大事件</h1> </section> </Template> ) // 公司產品 export const Products = () => ( <Template> <section className="products"> <h1>公司產品:主要經營 手機、電腦</h1> </section> </Template> ) // 聯系我們 export const Contact = () => ( <Template> <section className="contact"> <h1>聯系我們</h1> <p>公司電話:0755 - 12345678</p> </section> </Template> )
這時效果就達到了,左側的側邊欄始終存在。
React Router 4.0 ---- 嵌套路由和動態路由