寫在前面:
這一篇是我 使用scss + react + webpack + es6實現幻燈片 的進階篇,效果請點我,將會使用上redux的基礎用法,因為一開始沒有理解好redux的用法,單純看文檔,實現Todo List效果。但卻沒有形成思路,當想改造成自己東西時,一臉懵逼
,無從下手。后面動手整理思路,以下將會整理我的學習思路,如有出錯,請各位指教。
首先
1.你有接觸React 同時研究了 Redux,沒有的話這里有不錯的學習資源。 Redux中文文檔 Redux 指導與Redux 式編程 Redux 簡明教程
2.在火狐或者谷歌下載插件 React Devtools 這個將會原原本本的看到數據的傳遞,對於理解數據流動,必不可少
3.這一篇是基於我的前一篇基礎實現的,如果沒看過,建議你熟悉一下。
Redux 學習思路
下面的圖是store的數據流動的方式

數據流程:1.通過store.dispatch 方法觸發action
2.相應的reducers更新state
3.調用subscribe方法注冊執行回調
Action Creator => action => store.dispatch(action) => reducer(state,action) => next state
這里面有一個我經常混淆的地方:
action:描述一個狀態/動作 {type :' Set_Center_Filter ' , index} 這里面的type是必不可少的標識,比如是新增還是修改的標識。
actionCreator:創造一個action,是一個函數
export function setCenterFilter(index){ return {type : Set_Center_Filter , index} }
dispatch:dispatch(setCenterFilter(index)) 里面的 setCenterFilter 就是actionCreator的函數。dispatch(setCenterFilter 返回的action)。
reducer:(將是創建store的基礎)當dispatch執行之后,reducer就被自動執行,返回新的state
整體數據流動:
1.最外層的數據由 <Provider store={store}> <APP/> </Provider > 里面的store提供,讓容器里的 Connect(App)圖1知道從哪里獲得store對象(state來源)當做其自身props【1】
2.store由reducers通過 createCtore提供
3. reducers 由combineReducers 集合多個 reducer (todos , visibilityFilter)(整合到【1】里面的store)
4.以新增的todo為例,返回為 原數據加上新的數據,其被觸發方式為dispatch(action)
5.容器組件的disptach(action) 通過connect將需要過濾后的state傳給【1】中的<App/> 當做其props圖2


這就是整條數據鏈,至於剩下的組件,只需要拿到父組件的props當做自己的props,進行React的操作。
以上的內容比較羞澀難懂,還是需要自己好好琢磨。
接下來就是我的正文了,實現上一次的整合。
目錄結構:
|----build //編譯的環境 |--server.js |--webpack.config.js |----src //項目主入口 |--action |--components |--containers |--reducers |--index.html |--index.js |----static //靜態文件 |--css |--data |--imgs |--package.json |--.babelrc
項目分析:
1.分成兩個組件:圖片展示,按鈕控制(兩個組件都需要imgs數據)
2.reducers分為兩部分:imgs數據,current 用於存儲展示的索引
3.按鈕點擊改變current里面設置的索引參數(action.index),根據索引參數,改變各個展示圖片的 isCenter屬性。
4.基於上面的機制,action只有一個 ‘Set_Center_Filter’,用於判斷按鈕點擊這個動作。
接下來是我自己一般的創建的流程
各組組件先創建,然后模擬父組件本身就有props數據,這一步和React無異。
components/App.js
class App extends Component{ render(){return( <div className="slider"> <ShowPic imgs = [ { "img": "1.jpg", "h1": "Creative", "h2": "DUET",
"isCenter":"true",
"right" :"true"
}, { "img": "2.jpg", "h1": "Friendly", "h2": "Happy",
"isCenter":"true",
"right" :"true"
}]/> <SetCenterFilter imgs= [ { "img": "1.jpg", "h1": "Creative", "h2": "DUET",
"isCenter":"true",
"right":"true" }, { "img": "2.jpg", "h1": "Friendly", "h2": "Happy",
"isCenter":"true",
"right":"true" }] /> </div> ) } }
containers/ShowPic.js
import React,{Component} from 'react'
import MainI from './MainI'
export default class ShowPic extends Component{
render(){
return(
<div className="main">
{this.props.imgs.map((imgi , index)=>
<MainI {...imgi}
key={index}
isCenter={this.props.current == index} />
)}
</div>
)
}
}
containers/SetCenterFilter.js
import React,{Component} from 'react'
import CtrlI from './CtrlI'
export default class SetCenterFilter extends Component{
render() {
return(
<div className="ctrl">
{this.props.imgs.map((imgi , index) =>
<CtrlI {...imgi}
key={index}
isCenter = {this.props.current == index}
onClick={()=>this.props.onCenterClick(index)}/>
)}
</div>
)
}
}
containers/CtrlI.js
import React,{Component} from 'react'
export default class CtrlI extends Component{
render(){
var {isCenter , img , onClick} = this.props;
var ctrlClassName = 'ctrl-i' + (isCenter? ' ctrl-i_active' :'');
return(
<a className={ctrlClassName} onClick={onClick}>
<img src={img} alt=""/>
</a>
)
}
}
containers/MainI.js
import React,{Component} from 'react'
export default class MainI extends Component{
render(){
var {isRight , isCenter , h1 ,h2 ,img} = this.props;
var mainClassName = (isRight?'main-i main-i_right':'main-i')+
(isCenter ?' main-i_active':'');
return(
<div className={mainClassName}>
<div className="caption">
<h2>{h1}</h2>
<h3>{h2}</h3>
</div>
<img src={img} alt=""/>
</div>
)
}
}
上面的步奏基本和React沒有什么太大區別。
Action
export const Set_Center_Filter = "Set_Center_Filter"; export function setCenterFilter(index){ return {type : Set_Center_Filter , index} }
定義Action一定要對自己的場景熟悉,比如我的幻燈片只需要點擊更換state,所以只有一個action改變事件。
Reducer
import {combineReducers} from 'redux'
import { Set_Center_Filter } from '../actions/index'
/*
* 需要npm install json-loader
* 識別路徑中的JSON對象
* */
var imgData = require('../../static/data/imgDatas.json');
/* @type (function(){})() 立即執行函數
* @param imageDatasArr Json對象
* @return new JSON
* @功能 1.將圖片名信息轉成圖片URL路徑信息
* 2.根據 奇偶 添加isRight屬性
* */
imgData.forEach((item,index)=>{
item.isRight = index % 2;
item.img = '../static/imgs/'+item.img;
})
//單純的將 imgData 保存給state
function imgs(state = imgData){
return state
}
function current(state , action){
switch(action.type){
case Set_Center_Filter:
return action.index;
default:
return 0;
}
}
const SliderApp = combineReducers({
imgs,
current
})
export default SliderApp
這一段相當於核心步奏,通過改變current,返回對應索引。並在按鈕點擊時候對比后,添加class "_active"
components/App.js 修改內容
class App extends Component{ render(){ const {imgs,current} = this.props; return( <div className="slider"> <ShowPic imgs={imgs} current = {current}/> <SetCenterFilter imgs={imgs} current = {current} onCenterClick ={index => this.props.setCurrent(index)}/> </div> ) } } function mapStateToProps(state) { return { imgs: state.imgs, current : state.current }; } function mapDispatchToProps(dispatch) { return { setCurrent: (index) => dispatch(setCenterFilter(index)) }; } export default connect(mapStateToProps,mapDispatchToProps)(App)
connect用來連接React 與 Redux。
onCenterClick 點擊之后就會dispatch{type:Set_Center_Filter , index} 來更新store/state
connect將 state 的imgs屬性映射到了 ShowPic SetCenterFilter 的 this.props 屬性中,同時也把針對特定的Action Creator 的 dispatch 方法傳遞給了 this.props。這樣在 ShowPic SetCenterFilter 中僅僅通過 this.props 就可以完成 action dispatch 和 應用程序狀態獲取的動作
如果connect 函數省掉第二個參數,connect(mapStateToProps)(App),那么 dispatch 方法會被直接傳遞給 this.props。這不是推薦的方式,因為這意味着 App 需要了解 dispatch 的功能和語義了
最后就是
Index.js
import React from 'react' import {render} from 'react-dom' import {createStore} from 'redux' import {Provider} from 'react-redux' import App from './containers/App' import SliderApp from './reducers/reducers' let store = createStore(SliderApp) render( <Provider store={store}> <App/> </Provider>, document.getElementById('Pic_slider') )
最后一步就是用Provider讓 App.js的connect知道從哪里獲得store數據
以上就是這個React+Redux 實現幻燈片的思想,思想是自己的理解,如果有出錯,還望大家指出,一起學習。非常感謝樓下的朋友,幫我指正了錯誤。
以上的代碼均可以在我的Github上找到,與君共勉。
如果是原創文章,轉載請注明出處!!!
