zoukankan      html  css  js  c++  java
  • react + redux 实现幻灯片

    写在前面:

    这一篇是我 使用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.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

  • 相关阅读:
    内置函数,闭包。装饰器初识
    生成器
    百度ai 接口调用
    迭代器
    HashMap与ConcurrentHashMap的测试报告
    ConcurrentHashMap原理分析
    centos 5.3 安装(samba 3.4.4)
    什么是shell? bash和shell有什么关系?
    Linux中使用export命令设置环境变量
    profile bashrc bash_profile之间的区别和联系
  • 原文地址:https://www.cnblogs.com/QRL909109/p/5826895.html
Copyright © 2011-2022 走看看