React在Github上已經有接近70000的 star 數了,是目前最熱門的前端框架。而我學習React也有一段時間了,現在就開始用 React+Redux 進行實戰! 上回說到使用Redux-saga 管理 Redux 應用非同步操作,應用還是只有一個首頁.現在開始構建一個新的投稿頁面並使用 R ...
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 應用。
完整項目代碼地址:https://github.com/DigAg/digag-pc-react