react + redux 實現幻燈片

寫在前面:

這一篇是我 使用scss + react + webpack + es6實現幻燈片 的進階篇,效果請點我,將會使用上redux的基礎用法,由於一開始沒有理解好redux的用法,單純看文檔,實現Todo List效果。但卻沒有造成思路,當想改形成本身東西時,一臉懵逼,無從下手。後面動手整理思路,如下將會整理個人學習思路,若有出錯,請各位指教。css

首先html

1.你有接觸React 同時研究了 Redux,沒有的話這裏有不錯的學習資源。 Redux中文文檔 Redux 指導與Redux 式編程  Redux 簡明教程 react

2.在火狐或者谷歌下載插件 React Devtools 這個將會原本來本的看到數據的傳遞,對於理解數據流動,必不可少webpack

3.這一篇是基於個人前一篇基礎實現的,若是沒看過,建議你熟悉一下。git

Redux 學習思路

下面的圖是store的數據流動的方式es6

數據流程:1.經過store.dispatch 方法觸發actiongithub

              2.相應的reducers更新stateweb

              3.調用subscribe方法註冊執行回調npm

 

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.storereducers經過 createCtore提供

3. reducerscombineReducers 集合多個 reducer (todos , visibilityFilter)(整合到【1】裏面的store)

4.以新增的todo爲例,返回爲 原數據加上新的數據,其被觸發方式爲dispatch(action)

5.容器組件的disptach(action) 經過connect將須要過濾後的state傳給【1】中的<App/> 當作其props圖2

Connect(App)的數據爲stateAPP的數據爲上層的state變成自身props

這就是整條數據鏈,至於剩下的組件,只須要拿到父組件的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上找到,與君共勉。

若是是原創文章,轉載請註明出處!!!

by 邱XX:http://www.cnblogs.com/QRL909109/p/5826895.html

相關文章
相關標籤/搜索