react中實現導航欄狀態與地址綁定

1、項目初始化

1. 安裝與運行

構建項目:yarn create react-app my-app
啓動:yarn start
固然也能夠使用npm:css

  • 全局安裝:npm install -g create-react-app
  • 構建項目:npx create-react-app my-app
  • 啓動:npm start

2.安裝路由依賴

在項目中執行:npm install react-router-dom --savenode

3.在App.js中引入router

因爲簡單演示,就不單獨對router進行封裝了。
安裝完成後,咱們在App.js中引入路由相關組件BrowserRouterRouteSwitchRedirect
在頂部引入:import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom'
詳細代碼以下:react

import React, { Component } from 'react';
import Home from '@/views/home'
import Study from '@/views/study'
import Type from '@/views/type'
import Label from '@/views/label'
import About from '@/views/about'
import { Layout } from 'antd'
import Header from '@/components/Header'
import Persional from '@/components/Persional'
import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom'
const { Footer, Content, Sider} = Layout;
// 導入子組件
class App extends Component {
  render() {
    return (
      <div className="App" >
        <Layout>
          <Sider>
            <Persional />
          </Sider>
          <Content>
            <Router>
              <Header />
              <Switch>
                <Route path="/home" exact component={Home}></Route>
                <Route path="/study" component={Study}></Route>
                <Route path="/type" component={Type}></Route>
                <Route path="/label" component={Label}></Route>
                <Route path="/about" component={About}></Route>
                <Redirect from="/*" to="/home"></Redirect>
              </Switch>
              <Footer>Footer</Footer>
            </Router>
          </Content> 
        </Layout>
      </div>
    );
  }
}

export default App;

這裏用到了antd的Layout佈局組件進行佈局
首先咱們將咱們的視圖組件引入進來(import Home from '@/views/home'),並在Route標籤中配置:(以home爲例)<Route path="/home" exact component={Home}></Route>npm

4.編寫Header頭部導航組件

在components目錄下新建Header目錄,並在其目錄下新建index.js及index.scss文件,這裏使用scss進行編寫。
安裝命令:數組

npm install node-sass --save-dev 
npm install sass-loader --save-dev

爲了實現導航欄狀態與地址聯動,關鍵是要實現組件初始化時的處理邏輯,也就是組件掛載的時候,即在生命週期函數componentDidMount中實現。
要實現如下兩點:瀏覽器

  • 修改當前地址對應導航欄狀態
  • 監聽瀏覽器前進後退,即監聽history對象

關鍵代碼以下:sass

componentDidMount = () => {
    let moren = this.props.location.pathname
    let text = moren.substring(moren.lastIndexOf('/') + 1, moren.length)
    // 當訪問的目錄不在這個數組裏時候,當前狀態是home,即重定向到home頁面
    !['home', 'study', 'type', 'label', 'about', 'search'].includes(text) && (text = 'home')
    this.setState({
      current: text
    })
    // 監聽history變化
    history.listen((event) => {
      let test = event.pathname
      let text = test.substring(test.lastIndexOf('/') + 1, test.length)
      this.setState({
        current: text
      })
    })
  }

組件完整代碼以下:
index.js:antd

import React, { Component }  from 'react';
import { Row, Col, Menu  } from 'antd';
import { Link, withRouter } from 'react-router-dom'
import { HomeOutlined, FolderOpenOutlined, AppstoreOutlined, PushpinOutlined, UserOutlined, SearchOutlined } from '@ant-design/icons';
import './index.scss'
import { createBrowserHistory } from 'history';
const history = createBrowserHistory() // history模式

class Header extends Component {
  constructor(props) {
    super(props);
    this.state = {
      logo: '',
      current: 'home'
    }
  }
  handleClick = e => {
    this.setState({ current: e.key });
  }
  componentDidMount = () => {
    let moren = this.props.location.pathname
    let text = moren.substring(moren.lastIndexOf('/') + 1, moren.length)
    !['home', 'study', 'type', 'label', 'about', 'search'].includes(text) && (text = 'home')
    this.setState({
      current: text
    })
    history.listen((event) => {
      let test = event.pathname
      let text = test.substring(test.lastIndexOf('/') + 1, test.length)
      this.setState({
        current: text
      })
    })
  }
  render() {
    const { current } = this.state;
    return(
      <div className="header-wrapper">
         <Row>
          <Col span={18} push={6} className="right-box">
            <Menu onClick={this.handleClick} selectedKeys={[current]} mode="horizontal">
              <Menu.Item key="home" icon={<HomeOutlined />}>
                <Link to="/home">首頁</Link>
              </Menu.Item>
              <Menu.Item key="study" icon={<FolderOpenOutlined />}>
                <Link to="/study">學習</Link>
              </Menu.Item>
              <Menu.Item key="type" icon={<AppstoreOutlined />}>
                <Link to="/type">分類</Link>
              </Menu.Item>
              <Menu.Item key="label" icon={<PushpinOutlined />}>
                <Link to="/label">標籤</Link>
              </Menu.Item>
              <Menu.Item key="about" icon={<UserOutlined />}>
                <Link to="/about">關於</Link>
              </Menu.Item>
              <Menu.Item key="search" icon={<SearchOutlined />}>
                搜索
              </Menu.Item>
            </Menu>
          </Col>
          <Col span={6} pull={18} className="left-box">
            <strong className="logo-name">Deng</strong>
          </Col>
        </Row>
      </div>
    )
  }
}
export default withRouter(Header)

注意:爲了可以拿到this.props.location.pathname,須要使用withRouter處理組件,並把Header組件放在BrowserRouter標籤中。
這樣就可以實現導航欄狀態與地址綁定了react-router

相關文章
相關標籤/搜索