如何评价雷军宣称小米4小米6不锈钢边框手机边框成本价394元

haoduoshipin当我拿到一个前后端实现todolist的学习任务时,我应该怎么做? - 简书
当我拿到一个前后端实现todolist的学习任务时,我应该怎么做?
林老师在群里给大家布置了一个学习任务,为过一段时间的实战项目做准备。
任务是这样的:
前台用 react + redux,后台用 jersey + mybatis + mysql 写一个 todolist,可以对 todo 进行查看,删除,新增的功能
作为一个刚刚参加完ThoughtWorks暑期训练营的同学,我应该怎么来完成这个任务呢?
首先看一下两天之后部分同学的进展:
”我准备今天才开始,准备跟某茹同学一起合作学习。还是以前那种5w1h,然后分享,一天最多两个技术吧,这样想的?。想着先搞懂基, 然后结合写demo。“
”我是昨天开始学习的林老师任务。昨天主要学了mySQL,基本知识点差不多了,还没写demo练习,打算从今天开始和某秀同学结对学习java的相关东西。jersey + mybatis 我们暂定时间是一个星期,然后开始写todolist“
”老师,我前几天了解了一下docker和selenium,昨天看了jersey 后期准备和某红同学结对学习mytalis和mysql以及复习java的知识。暂定用一周来了解这些技术栈。“
看到同学们已经开始了,有了一个粗略的计划,并且没有忘记我们在训练营中学到的”合作学习“、”5w1h“、”分享“、”先写Demo“等方法,我觉得非常开心,你们很棒!只是我有些担心同学们的意愿是好的,但是在如何把它想得更细,并划分成可以有效执行的任务时,会遇到困难。
所以我在这里想聊一下,如果我接到了这个学习任务,我应该做什么以及怎么做。同学们在阅读的过程中,可以回想一下我们在训练营里所教授的东西,结合起来,希望在下一次遇到类似的任务时,也能按类似的方法给自己定出一个详细的学习计划。
先在前面说一下我的套路:
明确需求 -& 分解问题 -& 各个击破 -& 总结分享 -& 小步快跑,不断循环
明确这个学习任务的需求
当林老师告诉我们这个学习任务时,我们需要问自己(以及林老师)这几个问题:
老师为什么要给我们布置这个学习任务?
通过这个任务,我们要锻炼哪些软硬技能?
我们应该在什么时间前完成?
我们应该学到什么程度?
我们应该使用什么样的合作方式?自学,结对,还是建立一个学习小组?
这些学习任务中,哪些是最重要的,必须掌握的,哪些可以延迟?
这看起来是一个比较大的任务,我怎么对它进行拆分?
我怎么知道我掌握了?比如每个小任务应该有什么输出?
我最近有什么其它的事情要忙,怎么安排我的时间与精力?
这些问题大家都清楚了吗?至少有一些,我是不太清楚的(比如时间等),等林老师方便的时候问下他。
明确TodoList的需求
回顾一下林老师的任务:
前台用 react + redux,后台用 jersey + mybatis + mysql 写一个 todolist,可以对 todo 进行查看,删除,新增的功能
可以看到这里分为两个部分,一是”技术需求“,另一个是”功能需求“。
技术需求就是我们要学习的,可以稍后再看,我们先看一下功能需求:
写一个 todolist,可以对 todo 进行查看,删除,新增的功能
这个描述还是不太清楚的,不过我们其实还有一些背景信息的:之前我们在课堂上应该了解过这个著名的,所以我觉得这里说的就是上面的例子。如果不太确定,我们可以先看看,然后再问问林老师。
随便找了个例子(比如),看了一下它的demo,实际操作了一下,看看我们要做成什么样子。
这里先放个图:
我们可以在上面试试新增、删除、标记为完成、修改等功能,另外要注意底部左边的"n items left"的数字会变动,底部右边几个按钮还可以点击。
这时我可以把这个网址发给林老师,问问我们是不是要做成这个样子,底部那些按钮需不需要做。当然,我觉得林老师的回答肯定是,你能做就做,做不完就算了。。。
明确技术需求
然后我们再看看技术需求:
前台用 react + redux,后台用 jersey + mybatis + mysql
这里列出了主要的技术点,看起来不多,但是想一想,发现后面其实还有很多的隐藏信息:
我们的暑期训练营上刚刚培训完,当初教的各种实践和方法都要用上吧:分解任务,提问,画图,限时,Demo预研,等等
语言没有提(JavaScript和Java),这假设我们已经掌握了足够的基础知识。真的吗?
项目实践:构建工具,IDE使用,git+github,测试,结对,合作
这是一个学习任务,所以还有:自学能力的锻炼,规划与总结,分享
这样一想,似乎东西还不少啊。怎么办?我到底需要学哪些东西啊?
明确技术点
我们可以先把前面的技术需求再明确一些,只有再精细一些,我们才知道到底需要学习哪些东西。
这里,我把它们分为了”前端,后端,数据库,工具,其它“五个方面。
包管理工具:
构建工具:
资源打包工具:,及相应的插件
测试框架:或者, ,
前端框架:, ,
CSS框架:,或者
可能用到的库:,
语言:Java 8
构建工具: 或者
应用框架:,
操作数据库:
测试框架:, ,
数据库迁移工具:
图形管理工具:自行寻找
IDE:Webstorm,
版本控制工具:, ,
博客客户端:()
效率:IDE快捷键,Linux命令行
http api客户端:如,,
http协议,比如各种http code
天啊,怎么会这么多,我是不是想多了?当然,同学们可能一开始是想不到这么多的,但是随着项目进行,你会发现,到最后可能会比这还多。。。
那么有两个问题:
这些我们都需要在这个任务中学吗?
我们有没有办法合作学习?
关于第一个问题,大家留意一下上面加粗的技术点,就属于特别重要、必须掌握的,其它的可以参考已有代码或者根据自己的情况来定(或者分工,一人学一些,然后分享给其他人)
关于第二个问题,我们需要找到组织。
我们有十几位同学都在做相同的学习任务,我们能不能成立一个或者多个学习小组?我们已经有:
微信群(不公开)
github组织: (各位同学快发过来你们的github帐号)
论坛: 有问题在论坛上讨论啊,老师们会一直盯着(为了防止恶意注册,目前实行邀请制,大家把邮箱发给我)
当然,如果你们有自己的学习小组,也可以建立自己的github组织或者项目。
找个学习的小伙伴
有了组织,但是一个人学习还是太孤单,找一个小伙伴吧。两个人平时可以一起学习、讨论、写代码。
对于这个任务来说,找一个离自己近的,聊得来的,经常能坐在一起交流的同学更合适一些。
在学习的过程中,大家都需要通过写博客来记录和分享自己所学。由于大家在学差不多的东西,所以可以互相关注,及时看到别人的成果,节省自己踩坑和卡住的时间。
有些同学在csdn或者cnblogs等地方有自己的博客,我推荐大家使用,界面漂亮,写作体验非常好,能让人爱上写作。里面还可以使用markdown语法,写起来非常方便,另外还可以自动保存,历史版本比较,最赞的是可以发布的朋友圈让人打赏!说不定你写的东西解决了某个同学的问题,他一高兴打赏你十块八块的。
(插播:本文求打赏:)
然后每个人都有了博客,怎么才能最快的知道别人写了什么新博客呢?推荐使用一个叫的RSS订阅服务,它在安卓和苹果下都有客户端,比较好用。把同学的博客地址贴上去,就可以订阅了。一旦有新文章,就可以第一时间看到。
这里需要注意的是,简书并没有提供rss服务,不过我们可以使用,把简书上的用户地址贴上去,如果正确的话,就能生成相应的RSS链接,贴到inoreader里就可以啦。
现在知道老师为什么能第一时间知道同学们写了什么新博客吗?
inoreader安卓客户端
建议大家像老师一样,把大家的博客(甚至我们的BBS)都订阅上,需要链接的可以找老师,到时候把种子文件导入一下就行了,非常简单。
大家写博客肯定需要贴一大堆代码,还有各种标题、列表等等,使用普通的富文本编辑器,又麻烦又难控制,最终的效果通常也不怎么好看。
这时我们就可以花半个小时学习一下markdown,就可以高效的写出漂亮的博客了!而且这种语法在github/stackoverflow等各种地方都可以使用,受益终生啊。
需要注意的是,markdown有很多增强版,我们通常使用的是github的版本,参看这里:
你也可以试试在线的markdown编辑器,可以实时看到效果,方便学习,比如:
IntelliJ IDEA也提供了markdown插件,常用的编辑器如, 也都有Markdown插件。
分解任务,制定计划
前面我们明确了技术点,但真正动手的时候,我们还需要对它们进行进一步的细化,制定出可执行、可验证的更小的任务,才能动手做。在这个过程中,我们往往会发现一些事前没有考虑到的问题,产生更多的小任务。
这里需要注意两点:
最终的每一个小任务都是应该能在半天左右完成(熟练后一到两个小时内)。这样可以让我们在同一时刻需要关注的事情更少,并且能利用好每天的碎片时间,及时完成,及时分享,每天都能感觉到进步。
每个任务必须有输出,输出形式可以根据任务类型来定,比如图形、博客、代码、视频、分享、甚至教给别人等等
概念探索类的小任务
当我们第一次看到一个名词,对它一无所知,或者仅仅是听说过而已,我们应该怎么办?
不要慌张,也不要随便找了一篇文章或者一本书就从第一页一直读下去,而且要围绕着这个东西,问一些问题等等:
它是什么?
它能做什么?
它怎么来的?
它有什么重要概念?
先对这些最基本的问题做一定程度的发散,搜索资料(请使用google)获得一些信息,同时还会得到一些新的问题,然后再做发散,直到感觉那些问题或者答案跟我目前想学习的东西关系不大时,就可以及时停止,然后再针对最核心的概念与知识进行深入学习。
这里以webpack为例,看小波老师是怎么学习的。首先小波老师提出了一堆最基础的问题:
针对webpack的基础问题
然后找到了它们的答案:
找到了它们的答案
同时又引出了新的问题:
引出新的问题
以及新问题的答案:
我们可以看到,其中有的问题很早就结束了,比如“什么时候出现的?”,这可能是因为其答案并不容易搜到,但由于不是很重要,所以就算了。
其它的问题或者答案也可以根据我们的兴趣、精力,以及它与我们当前学习目标的紧密程度,我们来决定是否继续追问下去。
比如,这里是小波老师的最终版本:
最后的问题
当我们画完上面这个图时,我们对于webpack在宏观上就已经有相当程度的了解了,足以支持我们当成当前的学习任务(甚至都可以做个分享出来)。然后我们就可以深入到内部,去研究它的核心概念和方法(一般在文档中都会重点提到),画出一个“概念关系图”。
这里以redux为例(因为redux是必学,并且概念很多),给出相应的“概念关系图”:
redux的概念关系图
从图中我们可以看出,里面是真实的类或者方法的名字,通过连线表示出来它们之间的相互关系,通过数字来表示它们之间的调用顺序。
对于我们要研究的东西,相信只要我们能画出这两张图,我们对它的理解就达到很好的程度,后面再结合Demo预研,相信很快就可以掌握。对于jersey, mybatis,甚至mysql,我想大家都可以用上这种方法。
另外,在提问、寻找答案、画图的过程中,建议大家和自己的小伙伴一起,这样效率更高,效果更好。
对于这类小任务,我们的输出通常是这些:
自学提问图
概念关系图
相应的博客
功能验证类的小任务
当我们经历了前面的画图探索之后,虽然我们对它的整体情况有了一定程度的了解,但是我们还没有用真实可执行的代码来验证,这时我们再细分出一些demo预研的小任务。
这些小任务通常要比较小,从简单到复杂,每个小任务只完成一个功能集中且相对简单的任务(比如可以在一到两个小时内完整实现)。我们会创建一个新的目录,从零开始,创建一个独立、完整、仅包含要验证功能的最小代码的一个项目,然后把它push到github上,仅自己使用或者分享给同学。
代码中除了必要的代码外,还需要有一个README文件,里面用简洁的方式说明这个项目是做什么的,怎样配置和运行,有什么注意的地方,以及相关的资料链接等。分享给别人后,别人应该不需要再来问你,就可以自己运行起来。
在这个过程中,需要特别强调的几点:
项目命名非常重要,请尽量使用能够突出主要目的的关键字。比如我想写一个最简单的react项目,那么名字可能是react-hello-world-demo;如果想演示state的使用,那么是react-state-demo;如果想强调使用的是ES6中的class,那么可以是react-es6-class-hello-world-demo。当我们小项目越来越多时,你会觉得这些命名实在太重要了。
每个项目要完成的功能一定要单一。不论是自己以后使用,还是分享给别人,如果项目中混合了多个功能,基本上就没法使用,因为别人很难区分项目到底哪些代码是为这个功能,哪些是为那个功能,它们之间有没有联系。可以多建一些项目,但是不要混合在一起。
README一定要有,但要简洁。我们不必假设使用这个项目的是一个完全不了解它的小白,而应该是有一定经验的开发人员。这样,readme中可能给出一些关键的命令,以及一些需要的注意的点,必要的时候再加一些扩展阅读的链接即可。比如:
readme示例
依赖的版本号要明确。比如package.json中,最好使用固定的版本号,比如"react": "15.3.0",而不要使用默认的"react": "^15.3.0"。这是因为在js的世界里,依赖库的升级非常容易导致不兼容的现象,而当我们在一个比较久的时间之后来运行这些代码,很可能因为太多的库有新版本而导致程序出错。
当我们的demo项目越来越多后,为了方便对它们进行分类,我们可以在github上创建一些组织(orgnization),用于存放不同语言的Demo。
如果你不知道怎么做,就到看看老师的demo,找找感觉。我把我的两个demo orgnization放在上里,你会在上面发现很多有用的demo:
(当前超过100个demo)
(当前超过20个demo)
js-demos上的项目
java-demos上的项目
(注意,刚才我在查看的过程中,发现不少项目的README上的名字或者内容有错误,欢迎同学们指出。这是因为我创建了一些最基本的demo项目,然后在做新的demo时copy它们导致的)
对于这种类型的任务,我们的输出通常是一个github上的demo(可分享给其他同学),以及,如果过程中我们遇到了坑或者有意思的东西,可以写一篇博客分享出来。
细分小任务
前方高能。
对于前面提到的技术点,让我们对它们细分吧!
常用ES6语法(比如class, map/reduce/filter等)
使用webpack+babel来支持es6完整语法(如import/export)
使用React在页面上输出"Hello world"
使用React在页面上创建嵌套的两个组件
使用react-router来切换两个内容块
使用CSS或者Bootstrap来进行布局
使用React state的简单例子
纯Redux(不使用react)的简单的”点击按钮数字加1“
Redux + react简单的”点击按钮数字加1“
使用superagent向后台发AJAX请求
使用mocha运行最简单的测试
在测试中使用nock模拟http服务器
express例子(方便写服务器端来配合前端)
使用gulp来运行webpack打包
使用gulp运行测试
在IDEA中成功运行一个Java程序,输出"Hello World",使用1.6的语法
在IDEA中写一个最简单的JUnit测试,使用JUnit提供的assertEquals
在IDEA中写一个最简单的JUnit测试,使用assertj
使用gradle/maven来运行一个最简单的hello world程序
使用gradle/maven来运行一个最简单的测试
使用gradle/maven来运行一个有多个第三方依赖库的程序
使用jersey建立一个最简单的api,返回hello world即可
使用spring运行一个hello world,要使用到它的依赖注入功能
使用spring boot创建一个最简单的例子
使用mybatis来连接mysql数据,执行最简单的增删改查功能
使用fastjson进行对象与字符串之间的转换
在Linux下安装和启动mysql数据库
在Linux命令行下进行常见的数据操作
通过命令行对数据库进行备份
安装mysql桌面管理工具
在mysql桌面管理工具中操作数据库
结合实例使用常用的SQL语句
使用Webstorm进行Javascript项目开发的常用技巧
使用IntelliJ IDEA进行Java项目开发的常用技巧
如何把一个简单Javascript项目部署到Travis-CI上
如何把一个简单Java项目部署到Travis-CI上
如何把一个使用了mysql数据库的Java项目部署到Travis-CI上
简书有什么功能,如何切换成markdown,如何生成rss
Markdown的常用标签总结和示例
inoreader介绍与使用
postman的常用操作
httppie的常用操作
如何理解http协议
常用的http code介绍
对Restful的理解
上面的这些任务是我拍脑袋想出来的,可能并不全,以后会根据大家实际遇到的情况进行添加和修改。当然你也可以根据自己的情况,创建不同的小任务,这里仅供参考。
对于这里的每个小任务,大家可以根据自己的情况,来决定输出是什么。只需要记住最重要的一点:你的输出一定是可以分享给其他人的东西。
如何完成一个需要写代码的小任务
对于上面需要写代码的小任务,我们应该怎么做?
没错,你已经测到了,就是我们在训练营中已经练习了一遍又一遍的“基于管道图的任务分解大法”,或者用英文“基于pipeline的tasking大法”。
已经不记得的同学,请阅读下面几篇文章,这都是仝校长的智慧结晶:
以及我们核心的做事方式:
同时,大家不要忘了:
估时编程,反思问题
Test First
那我什么时候才能开始做Todolist?
前面列出来了这么多的小任务,我应该把它们全都(或者大部分都)掌握以后才开始做Todolist吗?
当然不是,如果这样的话,不知道要等多久了。。。
正确的做法是,我们需要开两条线并行前进:
Todolist线:完成林老师要求的Todolist功能
小任务线:分解小任务进行demo预研
我们应该从Todolist线开始,如果我们没有遇到问题,那就继续实现功能;当我们遇到了不会的东西时,离开Todolist线,把刚才遇到的问题抽象成一个或多个简单的小问题,转到小任务线,把它们实现出来;然后再回到Todolist线,用刚才学到的知识继续实现。
如果同学们组成了学习小组,我们就可以互相分享小demo,这样就可以省掉了很多自己研究的时间,同时也有了人可以讨论。
有问题及时提
知识至少分为两种:
信息型的:没法推理出来,需要搜索或者别人告诉
研究型的:可以根据已有信息推理出来,需要自己花时间去想去尝试
对于初学者来说,最浪费我们时间的往往都是信息型的知识。比如需要某个功能但是不知道什么库可以做到,怎么引用它,IDE怎么配置,有什么注意事项,哪里有什么坑,等等,往往一卡就是几个小时。这时候我们需要做的不是自己闷着头,不搞定不睡觉,而是及时提问,说不定几分钟就搞定了呢?
我们有哪些提问和信息获取渠道呢?
stackoverflow
你身边的同学
我们专门建立的bbs
同学的博客和项目demo
比如我可以提前告诉大家一个坑:我创建了一个哪怕非常简单的gradle项目,下载依赖居然卡几个小时,把我坑了很久。后来解决了,发现只要在build.gradle里加上一个jar包仓库的配置即可。当你遇到了同样的问题,问我的话,一分钟就能解决,不问的话,,,哈哈
另外我们在bbs专门创建了版,有问题第一时间上去问啊,老师们都盯着呢。(已经把这个bbs加入到我的inoreader阅读器里了)
学到了东西及时分享
再强调一下,当你学到了东西,不论是完成了小任务,还是解决了一个问题,一定要花时间把它分享出来。比如写博客,给同学讲,在网上直播写代码,或者在实验室定期组织分享活动,都可以。
也许这会花掉你的一些时间,但是要知道,这在锻炼你的软技能:你的思考能力、信息整理能力、写作能力、表达能力、同理心、公众演讲能力,你的收获可能会比你写的那些代码更大!
及时关注其他同学的输出
像老师一样,在手机上安装一个RSS阅读器(推荐inoreader),把同学们的博客,github,以及bbs全都加进去,这样当你没事的时候,就可以打开看一眼,也许只花10秒种就可以让你省掉几个小时。
最后,祝大家能通过这一个简单的Todolist学习任务,真正学到项目所需要的各种技能。
李鹏 @ ThoughtWorksRedux 入门教程(一):基本用法_javascript_ThinkSAAS
Redux 入门教程(一):基本用法
Redux 入门教程(一):基本用法
内容来源: 网络
React 只是 DOM 的一个抽象层,并不是 Web 应用的完整解决方案。也就是说,只用 React 没法写大型应用。
为了解决这个问题,2014年 Facebook 提出了Flux 架构的概念,引发了很多的实现。2015年,
出现,将 Flux 与函数式编程结合一起,很短时间内就成为了最热门的前端架构。
本文详细介绍 Redux 架构,由于内容较多,全文分成三个部分。今天是第一部分,介绍基本概念和用法。
零、你可能不需要 Redux
首先明确一点,Redux 是一个有用的架构,但不是非用不可。事实上,大多数情况,你可以不用它,只用 React 就够了。
曾经有人说过这样一句话。
"如果你不知道是否需要 Redux,那就是不需要它。"
Redux 的创造者 Dan Abramov 又补充了一句。
"只有遇到 React 实在解决不了的问题,你才需要 Redux 。"
简单说,如果你的UI层非常简单,没有很多互动,Redux 就是不必要的,用了反而增加复杂性。
用户的使用方式非常简单
用户之间没有协作
不需要与服务器大量交互,也没有使用 WebSocket
视图层(View)只从单一来源获取数据
上面这些情况,都不需要使用 Redux。
用户的使用方式复杂
不同身份的用户有不同的使用方式(比如普通用户和管理员)
多个用户之间可以协作
与服务器大量交互,或者使用了WebSocket
View要从多个来源获取数据
上面这些情况才是 Redux 的适用场景:多交互、多数据源。
总之,不要把 Redux 当作万灵丹,如果你的应用没那么复杂,就没必要用它。另一方面,Redux 只是 Web 架构的一种解决方案,也可以选择其他方案。
一、预备知识
阅读本文,你只需要懂 React。如果还懂 Flux,就更好了,会比较容易理解一些概念,但不是必需的。
Redux 有很好的
,还有配套的小视频(
)。你可以先阅读本文,再去官方材料详细研究。
我的目标是,提供一个简洁易懂的、全面的入门级参考文档。
二、设计思想
Redux 的设计思想很简单,就两句话。
(1)Web 应用是一个状态机,视图与状态是一一对应的。
(2)所有的状态,保存在一个对象里面。
请务必记住这两句话,下面就是详细解释。
三、基本概念和 API
Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。
Redux 提供 createStore 这个函数,用来生成 Store。
import { createStore } from &redux&;
const store = createStore(fn);
上面代码中, createStore 函数接受另一个函数作为参数,返回新生成的 Store 对象。
Store 对象包含所有数据。如果想得到某个时点的数据,就要对 Store 生成快照。这种时点的数据集合,就叫做 State。
当前时刻的 State,可以通过 store.getState() 拿到。
import { createStore } from &redux&;
const store = createStore(fn);
const state = store.getState();
Redux 规定, 一个 State 对应一个 View。只要 State 相同,View 就相同。你知道 State,就知道 View 是什么样,反之亦然。
3.3 Action
State 的变化,会导致 View 的变化。但是,用户接触不到 State,只能接触到 View。所以,State 的变化必须是 View 导致的。Action 就是 View 发出的通知,表示 State 应该要发生变化了。
Action 是一个对象。其中的 type 属性是必须的,表示 Action 的名称。其他属性可以自由设置,社区有一个
可以参考。
const action = {
type: &ADD_TODO&,
payload: &Learn Redux&
上面代码中,Action 的名称是 ADD_TODO ,它携带的信息是字符串 Learn Redux 。
可以这样理解,Action 描述当前发生的事情。改变 State 的唯一办法,就是使用 Action。它会运送数据到 Store。
3.4 Action Creator
View 要发送多少种消息,就会有多少种 Action。如果都手写,会很麻烦。可以定义一个函数来生成 Action,这个函数就叫 Action Creator。
const ADD_TODO = &添加 TODO&;
function addTodo(text) {
return {
type: ADD_TODO,
const action = addTodo(&Learn Redux&);
上面代码中, addTodo 函数就是一个 Action Creator。
3.5 store.dispatch()
store.dispatch() 是 View 发出 Action 的唯一方法。
import { createStore } from &redux&;
const store = createStore(fn);
store.dispatch({
type: &ADD_TODO&,
payload: &Learn Redux&
上面代码中, store.dispatch 接受一个 Action 对象作为参数,将它发送出去。
结合 Action Creator,这段代码可以改写如下。
store.dispatch(addTodo(&Learn Redux&));
3.6 Reducer
Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。
Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。
const reducer = function (state, action) {
// ...
return new_
整个应用的初始状态,可以作为 State 的默认值。下面是一个实际的例子。
const defaultState = 0;
const reducer = (state = defaultState, action) =& {
switch (action.type) {
case &ADD&:
return state + action.
default: 
const state = reducer(1, {
type: &ADD&,
payload: 2
上面代码中, reducer 函数收到名为 ADD 的 Action 以后,就返回一个新的 State,作为加法的计算结果。其他运算的逻辑(比如减法),也可以根据 Action 的不同来实现。
实际应用中,Reducer 函数不用像上面这样手动调用, store.dispatch 方法会触发 Reducer 的自动执行。为此,Store 需要知道 Reducer 函数,做法就是在生成 Store 的时候,将 Reducer 传入 createStore 方法。
import { createStore } from &redux&;
const store = createStore(reducer);
上面代码中, createStore 接受 Reducer 作为参数,生成一个新的 Store。以后每当 store.dispatch 发送过来一个新的 Action,就会自动调用 Reducer,得到新的 State。
为什么这个函数叫做 Reducer 呢?因为它可以作为数组的 reduce 方法的参数。请看下面的例子,一系列 Action 对象按照顺序作为一个数组。
const actions = [
{ type: &ADD&, payload: 0 },
{ type: &ADD&, payload: 1 },
{ type: &ADD&, payload: 2 }
const total = actions.reduce(reducer, 0); // 3
上面代码中,数组 actions 表示依次有三个 Action,分别是加 0 、加 1 和加 2 。数组的 reduce 方法接受 Reducer 函数作为参数,就可以直接得到最终的状态 3 。
3.7 纯函数
Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出。
纯函数是函数式编程的概念,必须遵守以下一些约束。
不得改写参数
不能调用系统 I/O 的API
不能调用 Date.now() 或者 Math.random() 等不纯的方法,因为每次会得到不一样的结果
由于 Reducer 是纯函数,就可以保证同样的State,必定得到同样的 View。但也正因为这一点,Reducer 函数里面不能改变 State,必须返回一个全新的对象,请参考下面的写法。
// State 是一个对象
function reducer(state, action) {
return Object.assign({}, state, { thingToChange });
// 或者
return { ...state, ...newState };
// State 是一个数组
function reducer(state, action) {
return [...state, newItem];
最好把 State 对象设成只读。你没法改变它,要得到新的 State,唯一办法就是生成一个新对象。这样的好处是,任何时候,与某个 View 对应的 State 总是一个不变的对象。
3.8 store.subscribe()
Store 允许使用 store.subscribe 方法设置监听函数,一旦 State 发生变化,就自动执行这个函数。
import { createStore } from &redux&;
const store = createStore(reducer);
store.subscribe(listener);
显然,只要把 View 的更新函数(对于 React 项目,就是组件的 render 方法或 setState 方法)放入 listen ,就会实现 View 的自动渲染。
store.subscribe 方法返回一个函数,调用这个函数就可以解除监听。
let unsubscribe = store.subscribe(() =&
console.log(store.getState())
unsubscribe();
四、Store 的实现
上一节介绍了 Redux 涉及的基本概念,可以发现 Store 提供了三个方法。
store.getState()
store.dispatch()
store.subscribe()
import { createStore } from &redux&;
let { subscribe, dispatch, getState } = createStore(reducer);
createStore 方法还可以接受第二个参数,表示 State 的最初状态。这通常是服务器给出的。
let store = createStore(todoApp, window.STATE_FROM_SERVER)
上面代码中, window.STATE_FROM_SERVER 就是整个应用的状态初始值。注意,如果提供了这个参数,它会覆盖 Reducer 函数的默认初始值。
下面是 createStore 方法的一个简单实现,可以了解一下 Store 是怎么生成的。
const createStore = (reducer) =& {
let listeners = [];
const getState = () =&
const dispatch = (action) =& {
state = reducer(state, action);
listeners.forEach(listener =& listener());
const subscribe = (listener) =& {
listeners.push(listener);
return () =& {
listeners = listeners.filter(l =& l !== listener);
dispatch({});
return { getState, dispatch, subscribe };
五、Reducer 的拆分
Reducer 函数负责生成 State。由于整个应用只有一个 State 对象,包含所有数据,对于大型应用来说,这个 State 必然十分庞大,导致 Reducer 函数也十分庞大。
请看下面的例子。
const chatReducer = (state = defaultState, action = {}) =& {
const { type, payload } =
switch (type) {
case ADD_CHAT:
return Object.assign({}, state, {
chatLog: state.chatLog.concat(payload)
case CHANGE_STATUS:
return Object.assign({}, state, {
statusMessage: payload
case CHANGE_USERNAME:
return Object.assign({}, state, {
userName: payload
default:
上面代码中,三种 Action 分别改变 State 的三个属性。
ADD_CHAT: chatLog 属性
CHANGE_STATUS: statusMessage 属性
CHANGE_USERNAME: userName 属性
这三个属性之间没有联系,这提示我们可以把 Reducer 函数拆分。不同的函数负责处理不同属性,最终把它们合并成一个大的 Reducer 即可。
const chatReducer = (state = defaultState, action = {}) =& {
return {
chatLog: chatLog(state.chatLog, action),
statusMessage: statusMessage(state.statusMessage, action),
userName: userName(state.userName, action)
上面代码中,Reducer 函数被拆成了三个小函数,每一个负责生成对应的属性。
这样一拆,Reducer 就易读易写多了。而且,这种拆分与 React 应用的结构相吻合:一个 React 根组件由很多子组件构成。这就是说,子组件与子 Reducer 完全可以对应。
Redux 提供了一个 combineReducers 方法,用于 Reducer 的拆分。你只要定义各个子 Reducer 函数,然后用这个方法,将它们合成一个大的 Reducer。
import { combineReducers } from &redux&;
const chatReducer = combineReducers({
chatLog,
statusMessage,
userName
export default todoA
上面的代码通过 combineReducers 方法将三个子 Reducer 合并成一个大的函数。
这种写法有一个前提,就是 State 的属性名必须与子 Reducer 同名。如果不同名,就要采用下面的写法。
const reducer = combineReducers({
a: doSomethingWithA,
b: processB,
// 等同于
function reducer(state = {}, action) {
return {
a: doSomethingWithA(state.a, action),
b: processB(state.b, action),
c: c(state.c, action)
总之, combineReducers() 做的就是产生一个整体的 Reducer 函数。该函数根据 State 的 key 去执行相应的子 Reducer,并将返回结果合并成一个大的 State 对象。
下面是 combineReducer 的简单实现。
const combineReducers = reducers =& {
return (state = {}, action) =& {
return Object.keys(reducers).reduce(
(nextState, key) =& {
nextState[key] = reducers[key](state[key], action);
return nextS
你可以把所有子 Reducer 放在一个文件里面,然后统一引入。
import { combineReducers } from &redux&
import * as reducers from &./reducers&
const reducer = combineReducers(reducers)
六、工作流程
本节对 Redux 的工作流程,做一个梳理。
首先,用户发出 Action。
store.dispatch(action);
然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 。
let nextState = todoApp(previousState, action);
State 一旦有变化,Store 就会调用监听函数。
// 设置监听函数
store.subscribe(listener);
listener 可以通过 store.getState() 得到当前状态。如果使用的是 React,这时可以触发重新渲染 View。
function listerner() {
let newState = store.getState();
component.setState(newState);
七、实例:计数器
下面我们来看一个最简单的实例。
const Counter = ({ value }) =& (
&h1&{value}&/h1&
const render = () =& {
ReactDOM.render(
&Counter value={store.getState()}/&,
document.getElementById(&root&)
store.subscribe(render);
上面是一个简单的计数器,唯一的作用就是把参数 value 的值,显示在网页上。Store 的监听函数设置为 render ,每次 State 的变化都会导致网页重新渲染。
下面加入一点变化,为 Counter 添加递增和递减的 Action。
const Counter = ({ value }) =& (
&h1&{value}&/h1&
&button onClick={onIncrement}&+&/button&
&button onClick={onDecrement}&-&/button&
const reducer = (state = 0, action) =& {
switch (action.type) {
case &INCREMENT&: return state + 1;
case &DECREMENT&: return state - 1;
default:
const store = createStore(reducer);
const render = () =& {
ReactDOM.render(
&Counter
value={store.getState()}
onIncrement={() =& store.dispatch({type: &INCREMENT&})}
onDecrement={() =& store.dispatch({type: &DECREMENT&})}
document.getElementById(&root&)
render();
store.subscribe(render);
Redux 的基本用法就介绍到这里。
来自:/blog/2016/09/redux_tutorial_part_one_basic_usages.html
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信

我要回帖

更多关于 不锈钢边框玻璃隔断 的文章

 

随机推荐