内容简介:先来看一下,完成文章标题所说的,需要完成哪些任务:
作者:殷荣桧@腾讯
先来看一下,完成文章标题所说的,需要完成哪些任务:
TODO LIST(计划列表) 1.redux中reducer的实现 2.redux中action的实现 3.redux中store的实现 3.5 先不使用redux,直接用react实现一个主题定制页面的开发 3.5.1 使用props传参完成父子组件共享同一个全局变量(演示全局变量的原始层层传递共享数据) 3.5.2 使用react提供的Context上下文完成父子组件全局变量的共享(演示全局变量使用react context 跨越组件共享数据) 4.结合自己实现的redux实现一个主题定制页面的开发 5.redux中的connect的实现。(结合react中的context实现) 6.结合connect react把主题定制页面再实现一遍 7.redux中添加mapStateToProps 8.redux中添加mapDispatchToProps 9.结合mapStateToProps,mapDispatchToProps 主题定制页面 10.redux中的provider的实现 11.使用provider重构代码 12.使用真正的react-redux替代进来,看项目是否正常运行。代码整理,provider中页面刷新相关的移动到connect,语法检查,错误检查,添加注释,合并commit 复制代码
接下来我们试着一个一个去实现。当然这其中包括了为什么需要redux的历史演化的过程,总的用了十几个commit来完成了这篇文章,基本上每个commit实现TODO list中的一个计划(在这墙裂推荐你使用source tree这个 工具 来查看各个commit都干了啥,修改了啥,对阅读源代码很有帮助)。在完成一个完整的功能后都会使用完整的demo进行演示,基本上可以覆盖redux的进化历程了。最后真正实现redux的部分连100行代码都不到,所以你千万不要被redux的名头吓跑。最后再不要脸一下,如果你觉得文章写得还行,欢迎您在我的 Github 中送上star.
接下来,就照着项目提交的commit一个一个的讲:
(1)commit1:完成TODO list规划 这个commit主要是完成了实现这篇文章所要完成的任务。也就是上面陈列的TODO list.
(2)commit2:完成reducer模块的功能 没有使用任何的构建工具,直接打开index.html就可以运行。需要在Google 调试工具的控制台中查看结果,界面上并无内容。这个commit主要就是实现了一个reducer,并在index.html中调用了reducer.js,主要是调试了一下reducer是否可以正常的运行。reducer实现的代码部分如下。
var reducer = (state = initialState, action) => { switch(action.type) { case CREATE_NOTE: { let currentId = state.nextNoteId; return { nextNoteId: currentId + 1, notes: { ...state.notes, [currentId]: action.content }, }; } case UPDATE_NOTE: { let {id, content} = action; return { ...state, notes: { ...state.notes, [id]: content } }; } default: return state; } } 复制代码
调试成功的结果如下:
(3)commit3-commit4:redux中action的实现
这两个commit主要实现了redux中action的定义。同样在index.html中引入了actions.js来对所写的action进行测试。
const CREATE_NOTE = "CREATE_NOTE"; const UPDATE_NOTE = "UPDATE_NOTE"; // 添加一条备忘录 let create_action = { type: CREATE_NOTE, content: '明天下午要开会' }; // 更新一条备忘录 let update_action = { type: UPDATE_NOTE, id: 1, content: '好像记错了,是明天上午要开会' }; 复制代码
下图为测试成功控制台的结果。
(4)commit5-commit6:完成store的实现,基本实现redux功能
function createStore(reducer) { let state = undefined; const subscribers = []; let store = { getState: () => state, dispatch: (action) => { state = reducer(state, action); subscribers.forEach(handler => handler()); }, subscribe: (handler) => { // handler就要比如备忘录有更新就发送通知到对应的人之类的 subscribers.push(handler); return () => { let index = subscribers.indexOf(handler); if (index >= 0) { // 防止搜索不到index为-1时,把subscribers最后一个删除了 subscribers.splice(0, index); } } } } store.dispatch(init_action); // 初始化一下备忘录 return store; } 复制代码
基本实现redux后,来测试一下自己写的redux是否正常运行。以下为正常运行的结果:
(5)commit7:使用props传参完成父子组件通信,完成主题切换 使用react的项目初始化工具,详情参考 react项目初始化工具 ,完成项目的初始化工作,并使用最原始的方式进行父子组件的传参,使用了props进行传参。使用这种方式的弊端就是,如果要从父向儿子,孙子,重孙....一直传到祖宗十九代的时候,每个子组件都要写向下传递的代码,非常的冗余和难以维护。在项目中才使用了几层代码都能感觉到代码的冗余和难以维护。(注意:项目中的Index.js需要修改为index.js才可以在my-app目录下使用npm run start运行,我的锅,不要意思,之后的commit都要改成index.js才可以正常运行)
class Content extends Component { render() { return ( <div> <span color={this.props.color} style={{color: this.props.color}}> 主内容区域 </span> <br/> <ChildContent switchColor={this.props.switchColor} color={this.props.color} ></ChildContent> </div> ); } } 复制代码
以下是完成的主题切换的效果:
(6)commit8:完成react提供的Context上下文完成父子组件全局变量的共享 为了避免代码的冗余。可以考虑使用react中提供的全局context来进行完成。这样就可以避免层层使用props来进行传参。在任何一行使用contextTypes就可以完成引用全局变量。但是这样写代码的弊端依然很明显。代码中依然存在冗余。但维护性相对于使用props较好。以下是使用contextTypes在组件中引用属性的方法。
class Title extends Component { static contextTypes = { color: PropTypes.string } render() { return ( <div style={{color: this.context.color}}>我是文章的标题</div> ); } } 复制代码
(7)commit9-commit10:结合自己实现的redux实现一个主题定制页面的开发
到这就可以结合自己开发的redux实现一个简单的主题定制页面的开发。主要在红色主题与蓝色主题之间切换。来测试自己所写的redux是否可以正常工作。主要实现的结果和上面相同。通过在my-app/的目录下运行npm run start就可成功启动页面。
(8)commit11-commit13:redux中connect的实现
connect实现部分的代码如下:
let connect = (WrappedComponent) => { class connect extends Component { static contextTypes = { store: PropTypes.object, } componentWillMount() { this.store = this.context.store; } render() { return <WrappedComponent store = {this.store}></WrappedComponent> } } return connect; } 复制代码
(9)commit14:redux中mapStateToProps的实现
mapStateToProps实现的代码如下:
let mapStateToProps = (state) => { return { themeColor: state.color, } } 复制代码
(10)commit15:redux中mapDispatchToProps的实现并结合自己实现的mapStateToProps和mapDispatchToProps更新主题修改小应用
let mapDispatchToProps = (dispatch) => { return { changeThemeColor: function(color) { dispatch({type: UPDATE_THEME, color}) } } } 复制代码
(11)commit16:redux中provider的实现,并使用其更新主题修改小程序
class Provider extends Component { static propTypes = { store: PropTypes.object, } static childContextTypes = { // 定义父子组件共享的变量 store: PropTypes.object, } getChildContext () { return { store: this.props.store } } componentWillMount() { this.props.store.subscribe(() => this.updateComponent()); } updateComponent() { // 每次store数据更新后重新渲染一下页面 this.setState({color: this.props.store.getState().color}); } render() { return this.props.children; } } 复制代码
(12)commit17-commit18:完成redux的简单仿写,并将项目中引用自己所写redux部分全部改成react中的redux,好看代码是否可行。
-import createStore from './redux/store'; +import {createStore} from 'redux'; -import Provider from './redux/provider'; +import {Provider} from 'react-redux'; 复制代码
通过上述的替换之后,切换主题的小应用工作正常(需要使用命令npm run dev,手贱,把start改成了dev),如下图所示。可见所仿写的redux基本成功,当然其中精细部分与原版有所差别,但是整体的原理上基本相似。所以到这基本上就了解了redux的工作原理,以后再也不要对redux的语法死记硬背了,因为你都已经写过一遍。
部门正在招新,为腾讯企业产品部,隶属CSGI事业群。福利不少,薪水很高,就等你来。有兴趣请猛戳下方两个链接。 www.lagou.com/jobs/521039… www.zhipin.com/job_detail/…
(如果发现文章中代码存在问题,请批评指正并留言,我会更新到文章以及代码中去,谢谢)
参考资料
code-cartoons.com/a-cartoon-i… cartoon intro to redux) zapier.com/engineering… (build yourself a redux) www.sohamkamani.com/blog/2017/0… (React-redux "connect" explained) codesandbox.io/s/github/re… (provider and connect example) huziketang.mangojuice.top/books/react… (React.js 的 context) huziketang.mangojuice.top/books/react… (动手实现 Redux(四):共享结构的对象提高性能,为什么需要使用...(spread operator)来提供性能) juejin.im/post/5a90e0… (聊一聊我对 React Context 的理解以及应用)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Perl高效编程
霍尔 / 胜春、王晖、张东亮、蒋永清 / 人民邮电出版社 / 2011-5 / 65.00元
《Perl高效编程(第2版)》,本书是Perl编程领域的“圣经级”著作。它提供了一百多个详实的应用案例,足以涵盖编程过程中经常遇到的方方面面,由此详细阐释出各种高效且简洁的写法。一起来看看 《Perl高效编程》 这本书的介绍吧!