Redux教程3:新增倒數計時
前面的教程裡面,我們搭建了一個簡單紅綠燈示例,通過在console輸出當面的倒數計時時間;由於介面上不能顯示倒數計時,使用者體驗並不良好,本節我們就新增一個簡單的倒數計時改善一下。
作為本系列的最後一篇文章,將示例如何處理多個Redux、React的情形;
1、建立Counter類
我們定義倒數計時的類名為 Counter ,建立所需要的檔案(夾):
mkdir actions/counter reducers/counter stores/counter components/counter views/counter
touch constants/Counter.js actions/counter/index.js reducers/counter/index.js stores/counter/index.js components/counter/index.js components/counter/redux.js components/counter/index.less components/counter/demo.js views/counter/index.hbs
建立 Counter 的 Redux 和 React 元件的過程就相當於重複了一下之前兩篇文章的過程,程式碼也不復雜,我這邊也就不貼上了。可自行參考程式碼,程式碼託管在 https://github.com/boycgit/demos/tree/master/traffic;
可以通過 http://localhost:3000/counter/redux 檢驗是否正常執行;
在假設使用者已經編寫上面的程式碼檔案的基礎上,我們繼續講解如何將 Counter 和 Light 兩個元件聯合起來。
2、建立入口檔案
Redux的三個原則之一 : 單一store,單一reducer。我們建立兩個檔案,分別整合之前所寫的 reducer 和 store 。
2.1、reducer入口檔案
建立 reducers/traffic.js
檔案,作為 主reducer 入口檔案:
import { combineReducers } from `redux`
import light from `./light/`
import count from `./counter/`
const rootReducer = combineReducers({
light,
count
});
export default rootReducer
這裡包含了最佳實踐法則, 將不同的狀態轉移關係寫進不同的js檔案,最後彙總到 index.js 中(這裡名為traffic.js,地位是一樣的) ,比如後期如果多出一種 “汽車的狀態轉移” 關係,只要新建對應的js檔案,然後再在index.js中的combineReducers
函式中多新增一行配置即可;
詳細的概念及作用請參考Redux的中文文件 Reducer
2.2、store入口檔案
建立 stores/traffic.js
檔案,作為 主store 入口檔案:
import { createStore } from `redux`
import rootReducer from `../reducers/traffic`
export default function trafficStore(initState){
return createStore(rootReducer,initState);
}
可以看到並沒有什麼工作量,只是多了幾行程式碼而已;
3、建立應用
前面建立的 Counter 和 Light 算是元件,將兩者結合起來,可以視作一款小應用了(假設應用名為traffic
);
為了方便管理,專門建立 App 資料夾來存放應用,並建立應用相關的等輔助內容(比如檢視等):
mkdir app app/traffic views/app
touch app/traffic/index.js app/traffic/index.less views/app/index.hbs views/app/traffic.hbs
核心是 app/traffic/index.js 檔案,其餘檔案只是其輔助作用,這邊也不重點講解,可自行到git clone後檢視;
3.1、初始化
在 app/traffic/index.js 中引入 Counter 和 Light 元件並設定初始化值:
import React, {Component, PropTypes} from `react`
import {render} from `react-dom`
import { Provider, connect } from `react-redux`
import { bindActionCreators } from `redux`
import * as LightActions from `../../actions/light/`
import * as CounterActions from `../../actions/counter/`
import Light from `../../components/light/`
import Counter from `../../components/counter/`
import trafficStore from `../../stores/traffic`
// 初始化狀態
let initLight = {
light:{
color:`green`,
time:`5`
}
}
let initCount = {
count:{
num : parseInt(initLight.light.time)
}
}
let initState = Object.assign({},initLight,initCount);
// 宣告store
let store = trafficStore(initState);
- 初始化的時候,我們從綠燈開始;
- 倒數計時的時間來自於 initLight.light.time ,這樣在初始化狀態的時候關聯起來兩個元件
- 將兩個元件的狀態(initLight,initCount)合併成 initState ,傳給應用的 store,以完成 應用store的初始化
3.2、建立React元件,並連結到Redux
緊接著,使用 connect 方法連結 Redux 和 React元件:
...
class App extends Component{
// 佔位
}
// 宣告 connect 連線
// 將 redux 中的 state傳給 App
function mapStateToProps(state){
return{
light:state.light,
count:state.count
}
}
// 繫結多個actions
function mapDispatchToProps(dispatch){
let boundLight = bindActionCreators(LightActions,dispatch);
let boundCount = bindActionCreators(CounterActions,dispatch);
return{
actions : Object.assign({},boundLight,boundCount)
}
}
// 宣告 connect 連線
App = connect(mapStateToProps,mapDispatchToProps)(App);
// 真正的連線
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById(`demo`)
)
形式和上篇提到的類似,細節略微有些不同:
- mapStateToProps中返回的物件有兩個屬性 light 和 count,在React元件中 對應 this.props.light 、 this.props.count
-
mapDispatchToProps 中現將兩個元件的方法先和
dispatch
繫結,合成一個物件之後再賦值,這樣在React元件中使用 this.props.actions 可以呼叫這兩個元件的所有的actions創造函式; - 最後使用
<Provider>
注入 store 例項;
3.3、完善App元件內容
最後,繫結store之後完善 App類 的程式碼,大部分的邏輯和前一篇的類似:
...
class App extends Component{
_bind(...methods){
methods.forEach((method)=>this[method] = this[method].bind(this));
}
constructor(){
super();
this._bind(`changeColor`,`handleClick`,`autoChange`);
this.state = {
timeId : null
}
}
changeColor(light,actions){ // 紅路燈變換規則
switch(light.color){
case `red`:
actions.changeGreen();
break;
case `green`:
actions.changeYellow();
break;
case `yellow`:
actions.changeRed();
break;
default:
actions.changeRed();
}
}
autoChange(){ // 自動更改紅綠燈
const { light,count, actions } = this.props;
let _self = this;
actions.countDown();
let curState = store.getState();
if(curState.count.num < 1){
this.changeColor(light,actions);
curState = store.getState();
actions.countInit(parseInt(curState.light.time));
}
// 自動更改
this.state.timeId = setTimeout(function(){
_self.autoChange();
},1000);
}
handleClick(e){ // 用點選模擬紅路燈
if(this.state.timeId){
clearTimeout(this.state.timeId);
this.state.timeId = null;
} else {
this.autoChange();
}
}
render(){
// 通過connect 注入 redux 的 dispatch 方法
const { light,count, actions } = this.props;
return (
<div id="traffic" onClick={this.handleClick}>
<Light light={light}/>
<Counter num={count.num}/>
</div>
)
}
}
// 宣告 connect 連線
...
變換的邏輯都在 autoChange 方法中
- 使用 actions.countDown(); 讓倒數計時減1,通過 store.getState();獲取更新後的狀態,因為如果直接使用count.num 獲取的是 更新之前 的狀態;
- 當 curState.count.num 小於 0 的時候,呼叫 this.changeColor(light,actions); 更改紅綠等的顏色,同時將 新的紅綠燈的time值初始化 Counter 元件,這樣就完成了兩者的繫結
3.4、預覽效果
在 http://localhost:3000/app/traffic 中檢視效果,效果正如此係列文章第一篇開頭所展示的那樣,紅綠燈搭配倒數計時執行:
紅綠燈初始狀態是 綠燈5s,繼而迴圈 黃燈3s -> 紅燈7s -> 綠燈5s -> 黃燈3s -> …
就這樣, Counter 和 Light 融洽地結合起來,完美,happy ending~
4、總結
到這裡,Redux 的入門教程算是完結;整個過程下來,你可以體會得到,React只需要關注逐漸的展示就行了,所有狀態的管理交由 redux
即可,這種繫結恰好體現了 容器元件和展示元件相分離 的開發思想: 只在最頂層元件(如路由操作)裡使用 Redux;內部元件應該像木偶一樣保持“呆滯”,所有資料都通過 props 傳入 。
這裡需要再強調一下:Redux 和 React 之間沒有關係。Redux 支援 React、Angular、Ember、jQuery 甚至純 JavaScript。
此係列文章僅僅是個開始,後續Redux還有許多高階內容需要學習,比如非同步資料流等處理。少年,加油吧~
相關文章
- JavaScript倒數計時JavaScript
- js——倒數計時JS
- JS倒數計時JS
- Kookjs 倒數計時JS
- 倒數計時34天
- CSS3動畫實現3D倒數計時效果CSSS3動畫3D
- laravel 9 倒數計時了Laravel
- 小程式倒數計時深究
- canvas環形倒數計時Canvas
- 倒數計時門栓(CountDownLatch)CountDownLatch
- js自動倒數計時程式碼,倒數計時完畢時自動停止迴圈JS
- js倒數計時 實現傳送驗證碼倒數計時60sJS
- Flutter倒數計時/計時器的實現Flutter
- 線上直播系統原始碼,預設倒數計時,自定義輸入時間倒數計時原始碼
- 視訊直播系統原始碼,倒數計時顯示,商品秒殺倒數計時原始碼
- JavaScript 年月日倒數計時JavaScript
- js cookie 頁面倒數計時JSCookie
- Android中handler倒數計時Android
- jQuery 倒數計時效果詳解jQuery
- Canvas環形倒數計時元件Canvas元件
- jquery 60s倒數計時jQuery
- 案例:倒數計時 js小案例JS
- js實現活動倒數計時JS
- js 活動倒數計時詳解JS
- js實現指定時間倒數計時JS
- css3實現的賽道倒數計時奔跑效果CSSS3
- layui table tr a標籤倒數計時 操作 重新整理以後繼續倒數計時UI
- Android 實現計數或者倒數計時 計時器 用法DemoAndroid
- win10 自帶倒數計時如何設定_win10開啟計時器倒數計時的方法Win10
- 傳送簡訊驗證,後按鈕倒數計時,防止重新整理倒數計時失效
- JavaScript 倒數計時關閉頁面JavaScript
- JavaScript 倒數計時60秒程式碼JavaScript
- JavaScript 倒數計時踩坑集錦JavaScript
- jquery實現60秒倒數計時jQuery
- 用宏實現PPT倒數計時
- 微信小程式之倒數計時元件微信小程式元件
- JavaScript倒數計時程式碼例項JavaScript
- setTimeout倒數計時效果程式碼