react + redux 实现幻灯片
Posted 邱XX
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.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上找到,与君共勉。
如果是原创文章,转载请注明出处!!!
以上是关于react + redux 实现幻灯片的主要内容,如果未能解决你的问题,请参考以下文章
“ES7 React/Redux/GraphQL/React-Native 片段”不适用于 javascript 文件。除了安装它,我还需要配置其他东西吗?