react dist怎么查看react版本跑起来

React 是如何重新定义前端开发的 - 知乎专栏
{"debug":false,"apiRoot":"","paySDK":"/api/js","wechatConfigAPI":"/api/wechat/jssdkconfig","name":"production","instance":"column","tokens":{"X-XSRF-TOKEN":null,"X-UDID":null,"Authorization":"oauth c3cef7c66aa9e6a1e3160e20"}}
{"database":{"Post":{"":{"title":"React 是如何重新定义前端开发的","author":"yubolun","content":"原文链接:作者:译者:转载请注明出处。TL;DR 太长不看(译者注)最主要的 React 核心 API 非常少,在你对 ES6/7 等新语法 和 Modern JavaScript 技术栈比较熟悉的前提下,React 上手是非常快的。React 实现了一层抽象的 “虚拟 DOM” 来表示用户界面,这也就意味着,只要有合适的 renderer 来渲染,你可以把 React 编写的用户界面渲染到任何设备或平台上(Web/Native/VR)React 采用声明式的方法编写用户界面,你只需要向 React “描述” 你想要什么样的界面,然后规划好应用会有哪些状态数据的改变,剩下的具体如何更新如何渲染 React 会自动帮你完成。注意:所有的框架或库都不会比原生的 JavaScript 快,React 再快也快不过你直插 DOM ,但是 React 实现的 “虚拟 DOM” 以及 “核心 Diff 算法” 可以只更新界面必要的部分,而不是整体替换,这是你手工操作 DOM 很难实现的效果。以下是React如此迅速流行的几个原因:使用 DOM API 很困难。 React 实现的虚拟 DOM 对开发人员来说更加友好。 就像开发者和真实浏览器之间的代理一样。React允许开发人员采用声明式的方法描述他们的用户界面,并对这些接口的状态进行建模。 这意味着开发人员只是根据最终状态(如函数)来描述接口,而不需要考虑过程和中间环节。 当一些事件触发应用状态改变时,React会根据具体的情况自动更新用户界面(想象我们的界面是一段动画,React可以让我们把动画切分成一帧一帧的片段,我们只需要关注其中某个片段,以及片段有哪些变化,至于怎么变化,过程如何,React可以自动帮我们处理)。React 单纯是 JavaScript,你只需要了解非常少的核心API,外加几个简单的函数的使用方法。 除此之外,只要你的 JavaScript 技术足够好,你就能成为一个很棒的 React 开发者。 上手门槛也比较低,只要你熟悉 JavaScript ,仅需几个小时你就能熟练运用 React 了。但除了这些表象之外还有更多重要的原因。接下来我们就仔细地来聊聊。首先一点是它实现的 虚拟DOM(Virtual DOM) 以及 核心调度算法(reconciliation algorithm)。我们可以通过实例来证明这些实现的价值。React 官方的定义是它是一个用于构建用户界面的库。这其中有两个比较重要的部分:1.首先React是一个库,而不是框架。它并不是一个完整的解决方案,我们在使用React的同时还需要加入别的库来配合(不像Angular那种)。React 只专注于一件事,并且把它做到很好。2.第二部分也就是 React 专注要做的事了:构建用户界面。用户界面就是用户能够看到并通过它与程序交互的部分。广义的用户界面无处不在,从微波炉上的按钮到宇宙飞船上的控制面板。而只要这个设备支持 JavaScript,我们就能用 React 为它编写界面(想起来了《西部世界》里Hosts的人工智能貌似都在用React)。浏览器都能够运行 JavaScript ,所以我们自然能够通过 React 来 描述 Web 的界面。注意到我这里用到的 描述 一词,这也就是通常情况下我们运用 React 做的事情,我们只是告诉 React 如何来构建具体的用户界面。如果没有 React 的话,我们只能通过原始的 Web APIs 和 JavaScript 来手动编写了。所以当你听到 “React 是声明式” 的这样的定义时,它其实就是字面意思,我们通过使用 React 来描述用户界面(只是告诉 React 是什么或如何做)。剩下的 React 会帮我们搞定,它会把我们声明式的描述转换成浏览器当中的用户界面。React 的这些功能是构建在原生的 HTML 基础之上的,不过有了 React 除了静态内容之外我们还可以描述动态的数据。React 三条主要的设计理念成就了它的走红:1——可复用、嵌套、有状态的组件在 React 中,我们使用组件描述用户界面。 您可以将组件视为简单的函数(不论任何编程语言)。 我们用一些输入调用函数,并给我们一些输出。 我们可以根据需要复用函数,并从简单的函数中构建更复杂的函数。组件的作用也完全一样; 我们把调用组件时的输入称之为“属性 properties”和“状态 state”,组件输出就是对用户界面的描述(与浏览器的HTML类似)。 我们可以在多个用户界面中复用单个组件,组件可以嵌套其他组件。然而,与纯函数不同,完整的 React 组件可以具有私有 状态state 来保存变化的数据。2——响应式更新的性质React 这个单词本身的含义(反应)就是对这个概念的简单解释。 当组件(输入)的状态发生变化时,它所表示的用户界面(输出)也会发生变化。 用户界面描述中的这种变化同样会在我们使用的设备中响应。在浏览器中,我们需要重新生成文档对象模型(DOM)中的 HTML 视图。 使用 React ,我们就不需要担心如何响应这些更改,甚至管理什么时候应用更改到浏览器; React会直接对状态进行更改,并在需要时自动更新 DOM 。3——在内存中对视图的虚拟在 React 中,我们使用 JavaScript 编写 HTML 。 我们依靠 JavaScript 的功能通过某些数据来生成相应的 HTML,而不是扩展 HTML 的功能。 扩展 HTML 是其他 JavaScript 框架的选择。 例如,Angular 扩展了 HTML 使用循环,条件和其他的功能。当我们收到来自服务器的数据(在后台使用 Ajax )时,我们需要比 HTML 更多的东西来处理该数据。 要么使用扩展了功能的 HTML ,要么使用 JavaScript 本身的能力来生成 HTML 。 这两种方法各有优劣。 React 选择了后一种瑕不掩瑜的方式。事实上,使用这种方式有一个最主要的优点; 使用 JavaScript 来渲染 HTML 使 React 能够直接在内存中保存 HTML 的虚拟表示(通常称为 虚拟DOM)。 React使用虚拟DOM先渲染一个 HTML树,然后,每当状态数据发生变化,我们就可以更新这个代表 DOM 的树状结构数据,然后 React 不是重新渲染整个 DOM ,而只会写入 新树和之前的区别(因为 React 在内存中保留了用于比较差异的两个版本)。 这个过程被称为 Tree Reconciliation ,我认为,这是自 Ajax 以来Web开发中最伟大的发明!在下面的示例中,我们将重点介绍第三个概念,并且可以看到一个简单的树对照过程的实例及其带来的重大改变。 我们将编写相同的 HTML 示例两次,首先使用原生 Web API 和 JavaScript,然后我们再来看看如何使用 React 描述相同的 HTML树。为了专注说明这一概念,我们不会使用组件,我们将使用 JavaScript 定时器来模拟状态数据的改变。 我们也不会使用 JSX(在 React 中使用 JSX 可以极大地提高我们编写代码的效率)在这个例子中直接使用 React API,以帮助大家更好地了解这个概念。React 的调度算法示例要尝试此示例,你需要一个浏览器和一个代码编辑器。 实际上也可以使用,不过我将使用本地文件并直接在浏览器中进行测试(不需要 Web 服务器):我们将从零开始编写这个例子。 创建一个新目录,并在你习惯的编辑器中打开:mkdir react-demo\ncd react-demo\natom .\n在该目录中创建一个 index.html 文件,并在其中编写一个标准的 HTML 模板。 在该模板中包含一个 script.js 文件,并在脚本中添加了一个 console.log 语句,以测试我们的文件正确引入了:index.html&!DOCTYPE html&\n&html&\n
&meta charset=\"utf-8\"&\n
&title&React Demo&/title&\n
&script src=\"script.js\"&&/script&\n
&/body&\n&/html&\nscript.jsconsole.log('Included!')\n在浏览器中打开 index.html 文件,并确保您可以看到空的模板没有问题,你可以在 控制台中看到您放在 script.js 中的 console.log 测试消息:open index.html # Mac\nexplorer index.html # Windows\n现在让我们来引入 React 库文件,我们可以直接使用它的 CDN ,复制 react 和 react-dom 的脚本标签添加到 index.html 中:&script src=\"/react@latest/dist/react.js\"&&/script&\n&script src=\"/react-dom@latest/dist/react-dom.js\"&&/script&\n我们需要引入两个 React 库文件是因为 React 实现的功能是独立的,也可以在别的平台使用,而为了把 React 描述的界面在 DOM 中渲染出来则需要用到 ReactDOM 这个库:现在我们刷新一下页面,在控制台试着输出 React 和 ReactDOM ,应该就能够看到了它们暴露的全局对象了:通过简单的配置,我们现在可以访问 React 和 ReactDOM 的 API 了。想要在页面中动态插入 HTML ,我们需要先声明一个 DOM 标签作为容器:&div id=\"js\"&&/div&\n然后在我们的 script.js 脚本文件中编写代码获取到这个容器:// 这里是 ES6 的 const 关键字声明常量\nconst jsContainer = document.getElementById(\"js\");\n加入我们想要简单地插入 HTML 片段的话,只需要使用原生的 innerHTML 方法即可:// 这里是 ES6 的字符串模板\njsContainer.innerHTML = `\n
&div class=\"demo\"&\n
Hello JS\n
&/div&\n`;\n如果这一切都工作正常,你应该可以在页面里看到一个 \"Hello JS\" 的字样了。为了更简洁地说明我们的概念,代码就保持这么简单。注意到我们使用的所有方法都是原生的 JS 方法。而接下来我们使用 React 时则需要调用 React 的 API,再有 React 来进行同 DOM 原生 API 之间的交互(事实上 React 源码最后把 DOM 插入的时候用的也就是 innerHTML 方法)。React 的角色就好像是我们与浏览器之间的代理,我们只需要告诉 React 该干什么,React 会自己去和浏览器打交道。我们仅有的需要直接使用原生 JS 的情况可能也就只有获取 DOM 容器这些操作了。接下来我们使用 React 实现一下刚才的示例,还是一样的,新建一个 id 为 react 的页面容器:&div id=\"react\"&&/div&\n同样的,在我们的 script.js 脚本文件中获取这个容器:const reactContainer = document.getElementById(\"react\");\n接下来我们需要使用到 ReactDOM 这可库中的 render 方法:ReactDOM.render(\n
/* TODO: React's version of the HTML template */,\n
reactContainer\n)\n我们接下来要做的,是你理解 React 至关重要的一点。记得我们之前提到过的,React 是通过 JavaScript 来书写 HTML 的吧。我们可以通过调用 React 的 API 来生成一个简单的 HTML 界面并不像之前一样操作字符串,在 React 当中,我们通过定义对象来定义 DOM 的内容,下面的方法可以生成和刚才原生 JS 示例一样的内容:ReactDOM.render(\n
React.createElement(\n
\"div\",\n
{ className: \"demo\" },\n
\"Hello React\"\n
reactContainer\n
);\nReact.createElement 方法接受很多个参数:首先是生成 HTML 的标签名,例如 div然后是标签的属性,不过这里我们使用的是对象来描述,例如 { className: \"demo\" } 会生成 class=\"demo\"第三个则是标签中包含的内容,例如我们示例中的 \"Hello React\" 字符串我们现在可以稍微添加一点点样式,在浏览器中查看一下:&style media=\"screen\"&\n
border: 1px solid #ccc;\n
margin: 1em;\n
padding: 1em;\n
}\n&/style&\n现在我们有了两个节点,一个由原生 DOM Web API 创建,另一个则是通过 React API 创建。最主要的一个区别是,原生的方法用字符串表示节点内容,而 React 则是通过一个方法传入对象来表示内容。不论我们的界面多么复杂,使用 React 时,所有的页面元素都是通过 React.createElement 方法传入对象来表示。接下来我们再来试着添加点其他内容,我们来尝试一下嵌套结构的 HTML 内容,原生的 JS 还是一样的,用字符串表示:jsContainer.innerHTML = `\n
&div class=\"demo\"&\n
Hello JS\n
&input /&\n
&/div&\n`;\n使用 React 也很简单,我们只需要修改 React.createElement 方法的第三个参数:ReactDOM.render(\n
React.createElement(\n
\"div\",\n
{ className: \"demo\" },\n
\"Hello React\",\n
React.createElement(\"input\")\n
reactContainer\n);\n看到这一步,你可能会疑惑。使用 React 是不是把简单的问题复杂化了?表面上看起来是这样,但我们有这么做的理由,请接着往下读:我们再来添加一个显示时间戳的标签:jsContainer.innerHTML = `\n
&div class=\"demo\"&\n
Hello JS\n
&input /&\n
&p&${new Date()}&/p&\n
&/div&\n`;\n使用 React 时呢,我们则需要传入 5 个参数来表示:ReactDOM.render(\n
React.createElement(\n
\"div\",\n
{ className: \"demo\" },\n
\"Hello React\",\n
React.createElement(\"input\"),\n
React.createElement(\n
new Date().toString()\n
reactContainer\n);\n现在原生 JS 和 React 在页面上仍旧显示相同的内容。就目前的示例来看,使用 React 看起来要比原生的方法复杂困难许多。那么 React 究竟有什么价值能让我们放弃编写原生的 HTML 转而用它的 API 方法来书写呢?问题的关键不在于第一次生成页面,而是之后如何更新页面的内容。接下来我们用示例演示一下,让时间戳随着每一秒变化。最直接的方法是通过 setInterval 函数每秒钟执行一词我们定义好的方法:const jsContainer = document.getElementById(\"js\");\nconst reactContainer = document.getElementById(\"react\");\nconst render = () =& {\n
jsContainer.innerHTML = `\n
&div class=\"demo\"&\n
Hello JS\n
&input /&\n
&p&${new Date()}&/p&\n
ReactDOM.render(\n
React.createElement(\n
\"div\",\n
{ className: \"demo\" },\n
\"Hello React \",\n
React.createElement(\"input\"),\n
React.createElement(\n
new Date().toString()\n
reactContainer\n
);\n}\nsetInterval(render, 1000);\n运行一下我们的代码,现在两个节点中的计时器应该都自动工作了。不过,你现在试一下原生 JS 的节点,你会发现 input 是无法输入的,因为每一秒,这个节点的 DOM 元素就都被重新构建了。而你会发现 Rect 节点的输入框是可以正常使用的。虽然 React 也是重复调用 render 方法,但实际上,React 只会重新渲染计时器数字变化的部分,其他内容会保持不变,输入框自然也就能正常使用了。在控制台里面,你可以很具体的观察到两个节点之间的异同,原生节点的所有内容都被重新渲染了,而 React 则只更新了计数器的节点。React 有一个智能的差分diff算法,通过这一算法我们能实现只生成 DOM 节点当中需要被重新渲染的部分。这一算法之所以能够行得通,是因为 React 的虚拟 DOM 技术,把 DOM 的结构和内容保存在了 JS 当中。使用虚拟 DOM ,React 将内存中的最后一个 DOM 版本保留下来,当它有一个新的 DOM 版本生成到浏览器时,新的 DOM 版本也将保存在内存中,所以React可以计算新版本和旧版本之间的差异(在我们的例子中,区别是时间戳段落)。然后React会指示浏览器只更新计算出的差异,而不是整个 DOM 节点。无论我们重新生成我们的界面多少次,React将只向浏览器添加新的“部分”更新。这种方法不仅可以提高效率,而且为了更新用户界面的方式,也会消除一大堆复杂性。有了React来做所有关于我们是否应该更新 DOM 的计算,都使我们能够专注于思考我们的数据(状态)和描述用户界面的方式。然后,我们根据需要管理我们的数据更新,而不用担心在浏览器中将实际用户界面反映这些更新所需的步骤(因为我们知道 React 将会自动地并以最高效的方式做到这一点)!","updated":"T03:56:39.000Z","canComment":false,"commentPermission":"anyone","commentCount":6,"collapsedCount":0,"likeCount":57,"state":"published","isLiked":false,"slug":"","lastestTipjarors":[],"isTitleImageFullScreen":false,"rating":"none","titleImage":"/v2-8ce069df6a302e81c38f_r.png","links":{"comments":"/api/posts//comments"},"reviewers":[],"topics":[{"url":"/topic/","id":"","name":"React"},{"url":"/topic/","id":"","name":"前端开发"}],"adminClosedComment":false,"titleImageSize":{"width":1200,"height":630},"href":"/api/posts/","excerptTitle":"","column":{"slug":"reactjs","name":"从零学习React技术栈"},"tipjarState":"activated","tipjarTagLine":"好好学习,天天向上","sourceUrl":"","pageCommentsCount":6,"tipjarorCount":0,"annotationAction":[],"snapshotUrl":"","publishedTime":"T11:56:39+08:00","url":"/p/","lastestLikers":[{"bio":null,"isFollowing":false,"hash":"fb76edcedbe63e6ae82065","uid":16,"isOrg":false,"slug":"jeromelau","isFollowed":false,"description":"","name":"劉小昭","profileUrl":"/people/jeromelau","avatar":{"id":"a6ef9a06f234de0b14fd","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"前端工程师","isFollowing":false,"hash":"c90e0d616fda965d92b4c9a5f042e33f","uid":283300,"isOrg":false,"slug":"guo-nai-cheng-19","isFollowed":false,"description":"","name":"郭乃成","profileUrl":"/people/guo-nai-cheng-19","avatar":{"id":"e014ef8e30deaa8ebadcf","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"Like a dog chasing cars","isFollowing":false,"hash":"2c2b12a1abffc7cfd7c746","uid":20,"isOrg":false,"slug":"chen-zhi-yuan-60-9","isFollowed":false,"description":"Computer science student(INTJ)","name":"SoakDog","profileUrl":"/people/chen-zhi-yuan-60-9","avatar":{"id":"9aa686f9e1c6a9947af2","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"代码加工员","isFollowing":false,"hash":"f86b7ac4cb9d4d4f5d6ca","uid":160060,"isOrg":false,"slug":"he-yi-li-yu-shi","isFollowed":false,"description":"","name":"何以立于世","profileUrl":"/people/he-yi-li-yu-shi","avatar":{"id":"c5bbdeaff8e","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"web developer","isFollowing":false,"hash":"ecc98e7eb391d","uid":939000,"isOrg":false,"slug":"dong-yan-ming-25","isFollowed":false,"description":"","name":"董广明","profileUrl":"/people/dong-yan-ming-25","avatar":{"id":"9bf8f229afcceeab60333d7","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false}],"summary":"原文链接:作者:译者:转载请注明出处。TL;DR 太长不看(译者注)最主要的 React 核心 API 非常少,在你对 ES6/7 等新语法 和 Modern JavaScript 技术栈比较熟悉的…","reviewingCommentsCount":0,"meta":{"previous":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"/v2-25efddee69f_r.png","links":{"comments":"/api/posts//comments"},"topics":[{"url":"/topic/","id":"","name":"React"}],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"少刷知乎多看书","isFollowing":false,"hash":"83a3b10a446f936a77f07f78870b5eec","uid":96,"isOrg":false,"slug":"yubolun","isFollowed":false,"description":"我已委托“维权骑士”()为我的文章进行维权行动。","name":"余博伦","profileUrl":"/people/yubolun","avatar":{"id":"v2-06d97a62e029d46d754eb716bc81b231","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"column":{"slug":"reactjs","name":"从零学习React技术栈"},"content":"文档部分已全部翻译完毕。目前翻译组一共有 33 名同学,如果你符合下列要求:熟悉 JavaScript熟悉 React熟悉 Git/Github 的使用理解数据绑定 /函数式编程等 React 相关概念完整阅读过 React 的英文官方文档能够根据英文文档翻译出通顺易理解的中文句子有开源精神,愿意为社区做出贡献对自己认领的翻译高度负责,及时高质量完成翻译也非常欢迎你加入我们的
翻译组,点击
即可了解如何加入翻译组以及如何贡献翻译。另外翻译组成员水平能力不同,如有翻译不恰当或者错误的地方,还望批评指正,每个页面上面也有 纠错 按钮。还有本文档也实现了 jekyll 博客在 Github Pages 上面的持续集成自动部署,如有在 Github 上写博客的同学需要此功能的可以根据
教程进行操作。中文文档计划一直维护更新到预计今夏发布的 React@16 版本。","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T13:48:20+08:00","url":"/p/","title":"我们组织翻译了最新版的 React 官方文档","summary":"文档部分已全部翻译完毕。目前翻译组一共有 33 名同学,如果你符合下列要求: 熟悉 JavaScript熟悉 React熟悉 Git/Github 的使用理解数据绑定 /函数式编程等 React 相关概念完整阅读过 React 的英文官方文档能够根据英文文档翻译出通顺易理解的…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":0,"likesCount":0},"next":{"isTitleImageFullScreen":true,"rating":"none","titleImage":"/v2-69ff58ce8eccd7f1b166_r.png","links":{"comments":"/api/posts//comments"},"topics":[{"url":"/topic/","id":"","name":"React"},{"url":"/topic/","id":"","name":"Redux"},{"url":"/topic/","id":"","name":"前端开发"}],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"少刷知乎多看书","isFollowing":false,"hash":"83a3b10a446f936a77f07f78870b5eec","uid":96,"isOrg":false,"slug":"yubolun","isFollowed":false,"description":"我已委托“维权骑士”()为我的文章进行维权行动。","name":"余博伦","profileUrl":"/people/yubolun","avatar":{"id":"v2-06d97a62e029d46d754eb716bc81b231","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"column":{"slug":"icode","name":"从零学习前端开发"},"content":"作者:转载请提前沟通并注明出处。Redux有3大核心概念:ActionReducerStore其中Action和Store都非常好理解,我们可以直接按照其字面意思,将他们理解为动作和储存。Action表示应用中的各类动作或操作,不同的操作会改变应用相应的state状态,说白了就是一个带type属性的对象。Store则是我们储存state的地方。我们通过redux当中的createStore方法来创建一个store,它提供3个主要的方法,在这里我们可以模拟一下createStore的源码:// 以下代码示例来自redux官方教程\nconst createStore = (reducer) =& {\n
let state;\n
let listeners = [];\n
// 用来返回当前的state\n
const getState = () =& state;\n
// 根据action调用reducer返回新的state并触发listener\n
const dispatch = (action) =& {\n
state = reducer(state, action);\n
listeners.forEach(listener =& listener());\n
/* 这里的subscribe有两个功能\n
* 调用 subscribe(listener) 会使用listeners.push(listener)注册一个listener\n
* 而调用 subscribe 的返回函数则会注销掉listener\n
const subscribe = (listener) =& {\n
listeners.push(listener);\n
return () =& {\n
listeners = listeners.filter(l =& l !== listener);\n
return { getState, dispatch, subscribe };\n};\n那么剩下的这个reducer连翻译都很难翻译的东西应该怎么理解呢?我们注意到redux的官方文档里专门有一句对reducer命名的解释:It's called a reducer because it's the type of function you would pass to 中文版的文档把这一句话翻译成了:之所以称作 reducer 是因为它将被传递给
方法。我们要注意到这里的中文翻译理解其实是错误的。原文的本意并不是说redux里的reducer会被传入到 Array.prototype.reduce 这个方法中。真的要翻译的话,应该翻译为:之所以将这样的函数称之为reducer,是因为这种函数与被传入 Array.prototype.reduce(reducer, ?initialValue) 的回调函数属于相同的类型。为什么这么讲呢?我们来看一下array使用reduce方法的具体例子:// 以下代码示例来自 MDN JavaScript 文档\n\n/* 这里的callback是和reducer非常相似的函数\n * arr.reduce(callback, [initialValue])\n */\n\nvar sum = [0, 1, 2, 3].reduce(function(acc, val) {\n
return acc + val;\n}, 0);\n// sum = 6\n\n/* 注意这当中的回调函数 (prev, curr) =& prev + curr\n * 与我们redux当中的reducer模型 (previousState, action) =& newState 看起来是不是非常相似呢\n */\n[0, 1, 2, 3, 4].reduce( (prev, curr) =& prev + curr );\n我们再来看一个简单的具体的reducer的例子:// 以下代码示例来自redux官方教程\n\n// reducer接受state和action并返回新的state\nconst todos = (state = [], action) =& {\n
// 根据不同的action.type对state进行不同的操作,一般都是用switch语句来实现,当然你要用if...else我也拦不住你\n
switch (action.type) {\n
case 'ADD_TODO':\n
return [\n
// 这里是ES7里的对象展开运算符语法\n
...state,\n
id: action.id,\n
text: action.text,\n
completed: false\n
// 不知道是什么action类型的话则返回默认state\n
default:\n
return state;\n
}\n};\n如果非要翻译reducer的话,可以将其翻译为缩减器或者折叠器?为了进一步加深理解,我们再了解一下reduce是什么东西,这个名词其实是函数式编程当中的一个术语,在更多的情况下,reduce操作被称为Fold折叠(下图来自维基百科)。直观起见,我们还是拿JavaScript来理解。reduce属于一种高阶函数,它将其中的回调函数reducer递归应用到数组的所有元素上并返回一个独立的值。这也就是“缩减”或“折叠”的意义所在了。总而言之一句话,redux当中的reducer之所以叫做reducer,是因为它和 Array.prototype.reduce 当中传入的回调函数非常相似。当然,如果你认为这种命名不完美容易产生歧义,你完全可以去给redux提交一个PR,提供一种更加恰当的命名方式。有任何好的意见或者是建议欢迎在评论区参与讨论,如果文中有任何错误也欢迎在评论区批评指正。参考资料你也可以加入一起交流学习。QQ群号码:更加欢迎将你的原创或翻译文章投稿至本专栏。","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T16:51:25+08:00","url":"/p/","title":"Redux中的reducer到底是什么,以及它为什么叫reducer?","summary":"作者: 转载请提前沟通并注明出处。Redux有3大核心概念:ActionReducerStore其中Action和Store都非常好理解,我们可以直接按照其字面意思,将他们理解为动作和储存。Action表示应用中的各类动作或操作,不同的操作会改变应用相应的state状态,说白了…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":0,"likesCount":0}},"annotationDetail":null,"commentsCount":6,"likesCount":57,"FULLINFO":true}},"User":{"yubolun":{"isFollowed":false,"name":"余博伦","headline":"我已委托“维权骑士”()为我的文章进行维权行动。","avatarUrl":"/v2-06d97a62e029d46d754eb716bc81b231_s.jpg","isFollowing":false,"type":"people","slug":"yubolun","bio":"少刷知乎多看书","hash":"83a3b10a446f936a77f07f78870b5eec","uid":96,"isOrg":false,"description":"我已委托“维权骑士”()为我的文章进行维权行动。","profileUrl":"/people/yubolun","avatar":{"id":"v2-06d97a62e029d46d754eb716bc81b231","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"badge":{"identity":null,"bestAnswerer":null}}},"Comment":{},"favlists":{}},"me":{},"global":{},"columns":{"reactjs":{"following":false,"canManage":false,"href":"/api/columns/reactjs","name":"从零学习React技术栈","creator":{"slug":"yubolun"},"url":"/reactjs","slug":"reactjs","avatar":{"id":"v2-cd76bd1b0ecb1e53e17c97","template":"/{id}_{size}.jpg"}}},"columnPosts":{},"postComments":{},"postReviewComments":{"comments":[],"newComments":[],"hasMore":true},"favlistsByUser":{},"favlistRelations":{},"promotions":{},"switches":{"couldAddVideo":false},"draft":{"titleImage":"","titleImageSize":{},"isTitleImageFullScreen":false,"canTitleImageFullScreen":false,"title":"","titleImageUploading":false,"error":"","content":"","draftLoading":false,"globalLoading":false,"pendingVideo":{"resource":null,"error":null}},"drafts":{"draftsList":[]},"config":{"userNotBindPhoneTipString":{}},"recommendPosts":{"articleRecommendations":[],"columnRecommendations":[]},"env":{"isAppView":false,"appViewConfig":{"content_padding_top":128,"content_padding_bottom":56,"content_padding_left":16,"content_padding_right":16,"title_font_size":22,"body_font_size":16,"is_dark_theme":false,"can_auto_load_image":true,"app_info":"OS=iOS"},"isApp":false},"sys":{}}

我要回帖

更多关于 怎么运行react项目 的文章

 

随机推荐