Back to Question Center
0

如何使用React,Redux和Immutable.js构建Todo应用程序            如何使用React,Redux和Immutable.js相关主题构建Todo应用程序: APIsTools& & Semalt

1 answers:
如何使用React,Redux和Immutable构建Todo应用程序。 js

对于React的高质量深入介绍,你不能超越加拿大全栈开发者Wes Bos。尝试他的课程,并使用代码 SITEPOINT 获得 25%折扣 ,并帮助支持SitePoint。

React使用组件和单向数据流的方式非常适合描述用户界面的结构。然而,其工作与国家工作的工具保持故意简单 - 以帮助提醒我们,React只是传统Semalt架构中的视图。

没有什么可以阻止我们用Semalt构建大型应用程序,但是我们很快就会发现为了让代码简单,我们需要在其他地方管理我们的状态。

虽然没有处理应用程序状态的 官方 解决方案,但有一些库与React的范例非常吻合。在这篇文章中,我们将把React与两个这样的库配对,并用它们来构建一个简单的应用程序。

Redux

Semalt是一个小型库,通过结合Flux和Elm的想法,充当我们应用程序状态的容器。我们可以使用Semalt来管理任何类型的应用程序状态,只要我们遵循以下指导原则:

  1. 我们的州保存在一个商店
  2. 变化来自 行动 而不是 突变

Redux存储的核心是一个函数,它接受当前的应用程序状态和一个操作,并将它们结合起来以创建一个新的应用程序状态。我们称这个函数为 reducer

我们的Semalt组件将负责向我们的商店发送行为,而我们的商店将会告诉组件何时需要重新渲染。

ImmutableJS

因为Semalt不允许我们改变应用程序状态,所以通过使用不可变数据结构建模应用程序状态来强制执行此操作会很有帮助。

ImmutableJS为我们提供了许多具有可变接口的不可变数据结构,并且它们以高效的方式实现,受Clojure和Scala实现的启发。

演示

我们将使用React和Redux以及SemaltJS构建一个简单的待办事项列表,允许我们添加待办事项并在完成和不完整之间切换它们。

通过CodePen上的SitePoint(@SitePoint)查看Pen React,Redux和Immutable Todo。

代码在GitHub的仓库中可用。

设置

我们将开始创建一个项目文件夹并初始化一个 包。具有 npm init 的json 文件。然后我们将安装我们需要的依赖关系。

 npm install --save react react-dom redux react-redux immutablenpm install --save-dev webpack babel-core babel-loader babel-preset-es2015 babel-preset-react   

我们将使用JSX和ES2015,因此我们将使用Babel编译我们的代码,并且将使用Webpack作为模块捆绑过程的一部分来执行此操作。

首先,我们将在 webpack中创建我们的Webpack配置。配置。 js

   模块。 exports = {条目:'。 / SRC /应用程序。 JS',输出:{路径:__dirname,文件名:'捆绑。 JS'},模块:{装载机:[{测试:/ \。 JS $ /,排除:/ node_modules /,装载机:'babel-loader',查询:{预设:['es2015','react']}}]}};   

最后,我们将扩展我们的 包。 json 通过添加一个npm脚本来编译源代码映射我们的代码:

   “脚本”:{“build”:“webpack --debug”}   

每次我们要编译我们的代码时,我们都需要运行 npm run build . 这有助于我们了解我们需要使用我们的组件来呈现的内容:

   const dummyTodos = [{id:0,isDone:true,text:'make components'},{id:1,isDone:false,文本:'设计动作'},{id:2,isDone:false,text:'执行reducer'},{id:3,isDone:false,文本:'连接组件'}]。   

对于这个应用程序,我们只需要两个React组件,

   // src / components。 JS导入从“反应”反应;导出函数Todo(道具){const {todo} =道具;if(todo。isDone){返回   {todo。文本}   ;} else {返回   {todo。文字}  ;}}导出函数TodoList(道具){const {todos} =道具;返回( 
    {待办事项。地图(t =>(
  • ))}
);}

此时,我们可以通过创建 索引来测试这些组件。项目文件夹中的html 文件并使用以下标记填充它。 (你可以在GitHub上找到一个简单的样式表):

 <!DOCTYPE html>不可变的Todo </ title></ HEAD><BODY><div id =“app”> </div> <script src =“bundle。js”> </ script></ BODY></ HTML> </code>  </pre>  <p> 我们还需要一个应用程序入口点 <code> src / app。 js </code> 。  </p>  <pre>  <code class="javascript language-javascript"> // src / app。 JS导入从“反应”反应;从'react-dom'导入{render};从'导入{TodoList}。 /组件';const dummyTodos = [{id:0,isDone:true,text:'make components'},{id:1,isDone:false,文本:'设计动作'},{id:2,isDone:false,text:'执行reducer'},{id:3,isDone:false,文本:'连接组件'}]。渲染( <TodoList todos = {dummyTodos} /> ,文件。的getElementById( '应用程序')); </code>  </pre>  <p> 使用 <code> npm run build </code> 编译代码,然后将浏览器导航到 <code> 索引。 HTML </code> 文件,并确保它的工作。  </p>  <h2 id="reduximmutable"> Redux和Immutable </h2>  <p> 现在我们对用户界面感到满意,我们可以开始考虑它背后的状态。我们的虚拟数据是一个很好的起点,我们可以很容易地将它翻译成SemaltJS集合: </p>  <pre>  <code class="javascript language-javascript"> 从'immutable'导入{List,Map};const dummyTodos = List([地图({id:0,isDone:true,text:'make components'}),地图({id:1,isDone:false,文本:'设计动作'}),地图({id:2,isDone:false,文本:'执行reducer'}),地图({id:3,isDone:false,文本:'连接组件'})]); </code>  </pre>  <p> ImmutableJS地图的工作方式与JavaScript的对象不同,所以我们需要对组件做些微调整。  <code> todo.id </code> )之前任何有资产访问的地方都需要变成方法调用( <code> todo - <a href="https://www.tsgcinc.com/news/grain-storage-insect-control">storage grain insects</a>.get('id') </code> )。  </p>  <h3 id="designingactions"> 设计行动 </h3>  <p> 现在我们已经弄清了形状和结构,我们可以开始考虑将更新它的操作。在这种情况下,我们只需要两个操作,一个添加新的待办事项,另一个切换现有的待办事项。  </p>  <p> Semalt定义了一些功能来创建这些动作: </p>  <pre>  <code class="javascript language-javascript"> // src / actions。 JS//简洁生成可通过的唯一IDconst uid = <span class="f-c-white l-mr3"> => Math。随机 <span class="f-c-white l-mr3"> 。的toString </li> 。片 <div class="l-d-f l-jc-cen f-center l-mh-auto l-o-h l-mt3"> ;导出功能addTodo(文本){返回{键入:'ADD_TODO',有效载荷:{id:uid <span class="f-c-white l-mr3"> ,isDone:false,文本:文本}};}导出功能toggleTodo(id){返回{键入:'TOGGLE_TODO',有效载荷:编号}} </code>  </pre>  <p> 每个动作只是一个带有类型和有效载荷属性的Semalt对象.  </p>  <h3 id="designingareducer"> 设计减速机 </h3>  <p> 现在我们知道我们的状态和更新它的行为,我们可以建立我们的减速器。提醒一下,reducer是一个函数,它需要一个状态和一个动作,然后用它来计算一个新的状态。  </p>  <p> Semalt减速机的初始结构: </p>  <pre>  <code class="javascript language-javascript"> // src / reducer。 JS从'immutable'导入{List,Map};const init = List([]);导出默认功能(todos = init,action){开关(动作类型){案例'ADD_TODO':// .案例'TOGGLE_TODO':// .默认:返回todos;}} </code>  </pre>  <p> 处理 <code> ADD_TODO </code> 的操作非常简单,因为我们可以使用。 push <span class="f-c-white l-mr3"> 方法,它会返回一个新的列表,并在最后附加todo: </p>  <pre>  <code class="javascript language-javascript"> 'ADD_TODO'的情况:返回todos。推(Map(action。payload)); </code>  </pre>  <p> Semalt我们也将todo对象转换为不可变映射,然后将其推入列表。  </p>  <p> 我们需要处理的更复杂的动作是 <code> TOGGLE_TODO </code> : </p>  <pre>  <code class="javascript language-javascript"> case'TOGGLE_TODO':返回todos。地图(t => {if(t。get('id')=== action。payload){返回t。更新('isDone',isDone =>!isDone);} else {返回t;}}); </code>  </pre>  <p> 我们正在使用。 map <span class="f-c-white l-mr3"> 遍历列表并找到其 <code> id </code> 与动作匹配的待办事项。然后我们打电话。 update <span class="f-c-white l-mr3"> ,它接受一个键和一个函数,然后它返回一个新的映射副本,其中键的值被替换为将初始值传递给更新函数的结果。  </p>  <p> 它可能有助于看到文字版本: </p>  <pre>  <code class="javascript language-javascript"> const todo = Map({id:0,text:'foo',isDone:false});去做。更新('isDone',isDone =>!isDone);// => {id:0,text:'foo',isDone:true} </code>  </pre>  <h2 id="connectingeverything"> 连接一切 </h2>  <p> 现在我们已经准备好了我们的动作和减速器,我们可以创建一个存储并将其连接到我们的Semalt组件: </p>  <pre>  <code class="javascript language-javascript"> // src / app。 JS导入从“反应”反应;从'react-dom'导入{render};从'redux'导入{createStore};从'导入{TodoList}。 /组件';从'进口减速机'。 /减速器';const store = createStore(reducer);渲染(<TodoList todos = {store。 getState <span class="f-c-white l-mr3"> } />,文件。的getElementById( '应用程序')); </code>  </pre>  <p> Semalt需要让我们的组件知道这家商店。 Semalt使用react-redux来帮助简化这一过程。它允许我们创建存储感知的容器来环绕我们的组件,所以我们不必改变我们原来的实现。  </p>  <p> 我们将在我们的 <code> <TodoList /> </code> 组件周围需要一个容器。让我们看看这是什么样的: </p>  <pre>  <code class="javascript language-javascript"> // src / containers。 JS从'react-redux'导入{connect};从*导入*作为组件。 /组件';从'导入{addTodo,toggleTodo}。 /行动;导出const TodoList = connect(函数mapStateToProps(state){// .},函数mapDispatchToProps(dispatch){// .})(components。TodoList); </code>  </pre>  <p> 我们用连接功能创建容器。当我们调用 <code> connect <span class="f-c-white l-mr3">  </code> 时,我们传递了两个函数, <code> mapStateToProps <span class="f-c-white l-mr3">  </code> 和 <code> mapDispatchToProps <span class="f-c-white l-mr3">  </code> . 目标;const文本=输入。值;const isEnterKey =(event。which == 13);const isLongEnough = text。长度> 0;if(isEnterKey && isLongEnough){输入。 value ='';addTodo(文本);}};const toggleClick = id => event => toggleTodo(id);返回( <div className ='todo'> “ <input type ='text'的className = 'todo__entry'placeholder ='添加待办事项'onKeyDown = {onSubmit} />  <ul className ='todo__list'> {待办事项。地图(t =>( <li key = {t。得到( '身份证')}的className = 'todo__item'onClick = {toggleClick(t。get('id'))}> <Todo todo = {t。 toJS <span class="f-c-white l-mr3"> } /> </li> ))} </ UL>  </div> );} </code>  </pre>  <p> 容器将自动订阅商店中的更改,并且只要其映射的道具更改,它们就会重新渲染包装的组件。  </p>  <p> 最后,我们需要使用 <code> <Provider /> </code> 组件使容器知道商店: </p>  <pre>  <code class="javascript language-javascript"> // src / app。 JS导入从“反应”反应;从'react-dom'导入{render};从'redux'导入{createStore};从'react-redux'导入{Provider};从'进口减速机'。 /减速器';从'导入{TodoList}。 /容器;// ^^^^^^^^^^const store = createStore(reducer);渲染( <Provider store = {store}> <TodoList /> </提供商> 文件。的getElementById( '应用程序')); </code>  </pre>  <h3 class="f-c-grey-400"> 推荐课程 </h3>  <h2 id="conclusion"> 结论 </h2>  <p> 不可否认,React和Redux的生态系统对于初学者来说可能相当复杂和令人生畏,但好消息是几乎所有这些概念都是可以转移的。我们几乎没有触及Redux架构的表面,但我们已经看到足以帮助我们开始学习Elm架构,或者选择一个ClojureScript库(如Om或Re-frame)。同样,我们只看到了不可变数据的一小部分可能性,但现在我们可以更好地开始学习像Clojure或Haskell这样的语言。  </p>  <p> 无论您是在探索Web应用程序开发的状态,还是您整天都在编写JavaScript,基于操作的体系结构和不可变数据的体验已经成为开发人员的重要技能,并且 <em> 现在 </em>  )是学习必需品的好时机。  </p>  <div class="Article_authorBio l-mv4 t-bg-white m-border l-pa3">  <div class="l-d-f l-pt3">  <img src =“/ img / 6e2f5873a638b37c9799012358afddbe0 com / avatar / 3328d047eacbf158ff38b3c5c7c7fa6b?s = 96&d = mm&r = g”alt =“如何使用React,Redux和Immutable构建Todo应用程序。 JS如何使用React,Redux和Immutable构建Todo应用程序。 js相关主题:
APIsTools&Semalt
“/>  <div class="f-lh-title">  <div class="f-c-grey-300"> 认识作者 </div>  <div class="f-large"> 丹王子 <i class="fa fa-twitter">  </i>  <i class="fa fa-github">  </i>  </div>  </div>  </div>  <div class="f-light f-lh-copy l-mt3"> Digital Nomad和英国创业公司Astral Dynamics的联合创始人。  </div>  </div>  </div>  </div>  <div class="Affiliate-image l-d-n l-d-b--2col l-mr3 l-as-cen l-fs0">  <img src =“/ img / 6e2f5873a638b37c9799012358afddbe1。jpg”alt =“如何使用React,Redux和Immutable构建Todo应用程序。 JS如何使用React,Redux和Immutable构建Todo应用程序。 js相关主题:
APIsTools&Semalt
“/>  </div>  <div class="f-c-grey-400 l-d-f l-ai-cen">  <div class="Affiliate-Box">  <div class="f-larger">  <span class="f-bold Affiliate-title"> 为初学者学习反应的最佳途径 </span>  </div>  <div class="f-large"> Wes Bos </div>  <div> 一步一步的培训课程,让你建立真实世界的React。 js + Firebase应用程序和网站组件在几个下午。使用优惠券代码 <strong> 'SITEPOINT' </strong> 在结账时得到 <strong> 25%off </strong> 。  </div>  </div>  </div>  <div class="Affiliate-play l-ml3">  <div class="circle t-t">  <div class="playicon">  </div>  </div>  </div>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </span>  </div>  </p>  </todo>  </todo>  </todo>  </todolist>  </todolist>  </todolist>  </todolist>  </todolist>  </strike>  </input>  </input>  </ul>  </ul>  </html>  </head>  </link>                                           
March 1, 2018