SPA与路由

  1. 单页Web 应用(single page web application,SPA)

  2. 整个应用只有一个完整的页面

  3. 点击页面中的链接不会刷新页面, 本身也不会向服务器发请求

  4. 当点击路由链接时, 只会做页面的局部更新

  5. 数据都需要通过ajax 请求获取, 并在前端异步展现

  6. 路由

    一个路由就是一个映射关系(key:value),key 为路由路径, value 可能是function/component。

    • 前端路由
    • 后端路由

react-router基本使用

相关文档:http://react-guide.github.io/react-router-cn/index.html

英文原版:https://reactrouter.com/web/guides/quick-start

  1. 安装

    yarn add react-router-dom
  2. 使用BrowserRouter组件包裹所有组件

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { BrowserRouter } from 'react-router-dom'
    import App from './components/app'
    
    ReactDOM.render(
      <BrowserRouter><App /></BrowserRouter>
      ,
      document.getElementById('root')
    );
  3. 在根组件中引入相关需要的路由组件

    import React, { Component } from 'react'
    import { NavLink, Switch, Route, Redirect } from 'react-router-dom'
    import About from '../views/about'
    import Home from '../views/home'
    export default class App extends Component {
      render() {
        return (
          <div>
            <div className='row'>
              <div className='col-xs-offset-2 col-xs-8'>
                <div className='page-header'>
                  <h2>React Router Demo</h2>
                </div>
              </div>
            </div>
            <div className='row'>
              <div className='col-xs-2 col-xs-offset-2'>
                <div className='list-group'>
                  <NavLink className='list-group-item' to='/about'>
                    about
                  </NavLink>
                  <NavLink className='list-group-item' to='/home'>
                    home
                  </NavLink>
                </div>
              </div>
              <div className='col-xs-6'>
                <div className='panel'>
                  <div className='panel-body'>
                    <Switch>
                      <Route path='/about' component={About}></Route>
                      <Route path='/home' component={Home}></Route>
                      <Redirect to='/about' />
                    </Switch>
                  </div>
                </div>
              </div>
            </div>
          </div>
        )
      }
    }

思想:重新包装一下NavLink组件,为其添加自己的属性。

import React, { Component } from 'react'
import { NavLink } from 'react-router-dom'

export default class MyNavLink extends Component {
  render() {
    return <NavLink {...this.props} activeClassName='activeClass' />
  }
}

使用时导入自己的组件MyNavLink即可。

嵌套路由

a8f9bc88-63c5-415e-8564-3a999e113aa9

在home组件中嵌套两个路由,home组件需要判断显示哪个路由,因此使用Switch组件进行包裹。

import React, { Component } from 'react'
import { Switch, Route, Redirect } from 'react-router-dom'
import MyNavLink from '../components/myNavLink'
import News from './news'
import Message from './message'
export default class Home extends Component {
  render() {
    return (
      <div>
        <h2>Home Route compoent</h2>
        <div>
          <ul className='nav nav-tabs'>
            <li>
              <MyNavLink to='/home/news'>News</MyNavLink>
            </li>
            <li>
              <MyNavLink to='/home/message'>Message</MyNavLink>
            </li>
          </ul>
          <div>
            <Switch>
              <Route path='/home/news' component={News} />
              <Route path='/home/message' component={Message} />
              <Redirect to='/home/news' />
            </Switch>
          </div>
        </div>
      </div>
    )
  }
}

在News或者Message组件中正常定义组件

import React, { Component } from 'react'

export default class Message extends Component {
    state = {
        messages: []
    }
componentDidMount() {
    // 模拟发送Ajax请求异步获取数据
    setTimeout(() => {
        const messages = [
            { id: 1, title: 'message001' },
            { id: 2, title: 'message002' },
            { id: 3, title: 'message003' },
            { id: 4, title: 'message004' }
        ]
        this.setState({ messages })
    }, 1000)
}
render() {
    return (
        <ul>
            <li>
                {this.state.messages.map((m, index) => (
                    <li key={index}>
                        <a href='???'>{m.title}</a>
                    </li>
                ))}
            </li>
        </ul>
    )
}
}

路由组件传参

通过链接传递数据

<Route
    path='/home/message/messagedetail/:id'
    component={messageDetail}
    />

:id表示在这个位置为收集一个键为id的对象。

接受参数,在跳转的组件中通过props.parmas接受参数。

const { id } = this.props.match.params

两种路由跳转方式

两种方式分别为replacepush。前者不会记录在历史记录里而后者会被记录。

aaa0112c-7bf7-49f1-ba11-132303ba5901

// 将ID作为参数传入函数
<button onClick={() => this.showDetail2(m.id)}>
    replace()查看
</button>

AntDesign库

官方:https://ant.design/index-cn

  1. 安装(手机端)

    yarn add antd-mobile
  2. 简单使用

    import React, { Component } from 'react'
    import { Button, Toast } from 'antd-mobile'
    import 'antd-mobile/dist/antd-mobile.css'
    export default class App extends Component {
      handClick() {
        Toast.info('666')
      }
      render() {
        return (
          <Button type='primary' onClick={this.handClick}>
            按钮
          </Button>
        )
      }
    }

按需引入

参考:按需加载

  1. 安装插件

    yarn add react-app-rewired babel-plugin-import customize-cra -D
  2. 修改package.json脚本运行文件

    "scripts": {
        "start": "react-app-rewired start",
        "build": "react-app-rewired build",
        "test": "react-app-rewired test --env=jsdom"
    }
  3. 创建config-overrides.js文件

    const { fixBabelImports, override } = require('customize-cra')
    module.exports = override(
      fixBabelImports('import', { libraryName: 'antd-mobile', style: 'css' })
    );