React 实践项目 (四) React-Router

1,494 阅读4分钟

React 实践项目 (四) #9

Open
Yuicon opened this Issue 2 days ago · 0 comments

Comments

Projects
None yet
1 participant
Contributor

Yuicon commented 2 days ago edited

React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架。而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战!

上回说到使用Redux-saga 管理 Redux 应用异步操作,应用还是只有一个首页.现在开始构建一个新的投稿页面并使用 React-Router 进行路由管理.

React 实践项目 (一)

React 实践项目 (二)

React 实践项目 (三)

React 实践项目 (四)

- 首先我们来构建投稿页面

创建 src/containers/SubmitEntry.js

/**
 * Created by Yuicon on 2017/7/13.
 * https://github.com/Yuicon
 */
import React, {Component} from 'react';
import {Button, Form, Input, Switch, Notification} from "element-react";
import {connect} from "react-redux";
import {createEntryAction} from '../../redux/action/entries';
import './SubmitEntry.css';

@connect(
  (state) => {
    return ({
      entries: state.entries,
    });
  },
  {createEntryAction: createEntryAction}
)
export default class SubmitEntry extends Component {

  constructor(props) {
    super(props);

    this.state = {
      form: {
        title: '',
        content: '',
        original: true,
        originalUrl: null,
        english: false,
        type: 'article',
      },
    loading: false,
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.entries.get('saveSuccess')) {
      Notification.success({
        title: '成功',
        message: '投稿成功',
        duration: 1500
      });
      this.setState({form: {
        title: '',
        content: '',
        original: true,
        originalUrl: null,
        english: false,
        type: 'article',
      }});
    } else if (nextProps.entries.get('error')) {
      Notification.error({
        title: '错误',
        message: nextProps.entries.get('error'),
        type: 'success',
        duration: 1500
      });
    }
    this.setState({loading: false});
  }

  handleSubmit = () => {
    this.props.createEntryAction(this.state.form);
    this.setState({loading: true});
  };

  handleChange = (key, value) => {
    this.setState({
      user: Object.assign(this.state.form, {[key]: value})
    });
  };

  render(){
    return(
      <div className="SubmitEntry-container">
        <div className="head">
          <h2>推荐文章到掘金</h2>
          <p>感谢分享,文章的审核时间约1-2个工作日</p>
        </div>
        <div className="entry-form">
          <Form model={this.state.form} labelWidth="80" onSubmit={this.handleSubmit}>
            <Form.Item label="分享网址">
              <Input value={this.state.form.originalUrl} onChange={this.handleChange.bind(this, 'originalUrl')}/>
            </Form.Item>
            <Form.Item label="标题">
              <Input value={this.state.form.title} onChange={this.handleChange.bind(this, 'title')}/>
            </Form.Item>
            <Form.Item label="描述">
              <Input value={this.state.form.content} onChange={this.handleChange.bind(this, 'content')}/>
            </Form.Item>
            <Form.Item >
              <Switch
                value={this.state.form.original}
                onChange={this.handleChange.bind(this, 'original')}
                onText="原创"
                offText="转载">
              </Switch>
            </Form.Item>
            <Form.Item >
              <Switch
                value={this.state.form.english}
                onChange={this.handleChange.bind(this, 'english')}
                onText="英文"
                offText="中文">
              </Switch>
            </Form.Item>
            <Form.Item >
              <Button type="primary" onClick={this.handleSubmit} loading={this.state.loading}>
                发布
              </Button>
            </Form.Item>
          </Form>
        </div>
      </div>
    )
  }
}

相关的Redux部分已经讲过.就不重复介绍了,感兴趣的可以查看示例代码

  • 页面创建好了,开始使用 React-Router 管理路由

  • 首先是添加依赖

编辑 package.json

     // react-router-dom 包含 react-router
    "react-router-dom": "^4.1.1",
  • 编辑 App.js
/**
 * Created by Yuicon on 2017/6/25.
 */
import React, { Component } from 'react';
import {BrowserRouter as Router,Route} from 'react-router-dom'
import './App.css';
import Index from "../Index/Index";
import Header from "../Header/Header";
import SubmitEntry from "../SubmitEntry/SubmitEntry";

export default class App extends Component {

  render(){
    return(
    <Router>
      <div className="App">
        <Route component={Header}/>
        <Route exact path="/" component={Index}/>
        <Route exact path="/submit-entry" component={SubmitEntry}/>
      </div>
    </Router>
    )
  }

}

Router:

Router 一共有三种,我们采用的是常用的 browserHistory

browserHistory h5的history
hashHistory 老版本浏览器的history
memoryHistory node环境下的history,存储在memory中

Route :

每个 Route 标签都对应一个UI页面,它的职责就是当页面的访问地址与 Route 上的 path 匹配时,就渲染出对应的 UI 界面。
<Route component={Header}/> 是没有 path 的,这意味着在每个页面都会渲染出 Header 组件.

exact :

Route 上的 exact props 表示采用严格匹配,页面的访问地址与 Route 上的 path 必须一样
<Route exact path="/" component={Index}/> 只会匹配 '/' , 不会匹配 '/submit-entry'
<Route path="/" component={Index}/> 会匹配所有 '/' 开头的路径

history:

常用方法

push(path, [state]) 在历史堆栈信息里加入一个新条目。
常用于页面跳转,如:this.props.history.push('/'); 跳转至首页

replace(path, [state]) 在历史堆栈信息里替换掉当前的条目 与 push 的区别是无法通过历史堆栈返回跳转前的页面

goBack() 等同于浏览器的后退键

match:

match 对象包含了 Route 如何与 URL 匹配的信息,具有以下属性:

params: object 路径参数,通过解析 URL 中的动态部分获得键值对

isExact: bool 为 true 时,整个 URL 都需要匹配

path: string 用来匹配的路径模式,用于创建嵌套的

url: string URL 匹配的部分,用于嵌套的

常用于获取路径中的参数
有这样一个路由 <Route path="/:id" component={Child}/>
在 Child 中可以这样获取到 id 参数 this.props.match.params.id

  • 结语

现在我们得到了一个可以见人的应用了,剩下的大部分是一些业务代码。为了检验效果当然是选择部署到服务器。下篇文章将会介绍利用 nginx 的 docker 镜像部署 React 应用。
完整项目代码地址:github.com/DigAg/digag…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can't perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.