白癜风要怎么治疗好 http://news.39.net/bjzkhbzy/180423/6185455.html在这篇文章,作者将使用React.js和Redux.js前端技术,并通过调用RubyonRailsAPI,手把手教会你如何创建一个完美的全栈Web应用程序。
作者
Anne-LaureChadeyas
译者
弯月,责编
屠敏
以下为译文:
在学习了多节教学课程,并实践4个项目之后,现如今我终于可以谈一谈我的最后一个项目了。在参加FlatironSchool的这个在线软件开发自学课程时,我知道我必须完成五个项目才能毕业。最后一个项目似乎一直遥不可及,因为这个项目需要大量我还没有掌握的技能。但现在,我终于可以提交这个项目了。
最后这个项目的目标是要构建一个漂亮的单页应用,前端使用React.js和Redux.js,调用RubyonRailsAPI。
单页应用
首先,什么是单页应用?单页应用就是一个网站或Web应用程序,根据用户的动作或行为,动态地改写当前页的内容,而不是从服务器加载全新的页面。实现途径有两种:
在一次页面加载中读取所有的页面内容。但考虑到应用程序的复杂性,这样做可能需要很长时间,因此会影响用户体验。在某个用户事件后,向服务器请求相应的内容。常见的用户事件包括点击按钮、页面向下滚动、鼠标悬停在某个元素上、按下键盘上的某个键等。对于复杂的应用程序,第二种方式更常见。毕竟,单页应用存在的原因就是它能提供更为平滑的用户体验,不会被全页重新加载打断。
从代码的角度来讲,单页应用意味着整个应用程序中只有一个HTML页面,通常这个页面名为index.html。
构建应用程序结构
应用程序分为两部分:前端和后端。前端是用户交互的部分,即用户界面。后端负责服务器与用户界面之间的连接。构建应用程序有两个选择:
第一个选择就是把前端和后端都放在同一个代码仓库中(比如GitHub上的代码仓库)。第二个选择是建立两个代码仓库,一个用于后端,一个用于前端。这样做有几个好处,其中之一就是后端(比如本文中的API)可以被多个前端复用,另一个好处就是编辑器中管理的目录更小。上述两种方法并没有对错之分。基于上面给出的两个理由。我在构建应用程序时选择了使用两个独立的代码仓库、
第一个代码仓库是后端的。我在终端中使用下述命令创建了一个Rails应用程序作为API,不过没有任何视图。这跟创建普通的Rails应用程序是一样的,只不过多了一个参数。
railsnewmy_app_backend--api
至于前端,我采用了create-react-app生成器。
npxcreate-react-appmy_app_frontend
这两个命令可以帮我建好所需的一切文件。
关于组件的类型
该项目的技术要求是,至少需要写两个容器组件,以及5个无状态组件。React中的组件是界面的基本构成元素。它可以从父组件接受输入(通过props访问),还可以重用。
下面详细介绍一下容器组件和无状态组件。首先需要解释一下什么是状态(state)。状态就是可能会改变的数据。状态改变可能有多种原因,其中之一就是数据库更新导致状态变化,另一个原因就是用户修改了数据。
容器组件也称为有状态组件,而无状态组件也称为表现组件。容器组件和表现组件并没有严格的区分,每个开发者都可以按照自己的意愿来组织各个组件。但一般而言,容器组件是有状态的,可以通过其状态改变来跟踪,而表现组件没有状态,它可以显示传递过来的props,也可以永远显示固定的内容。
至于本文讨论的应用程序,我决定采用最基本的分割方法。我给API中的每个模型都建立了一个容器组件。随着项目的进行,我删掉了一些不再需要的组件,同时还添加了一些其他组件。有状态组件基本上都是表单。最好的例子就是注册表单和登录表单。在React的表单中,每次用户输入都会导致状态的变化,可能是局部状态变化,也可能是Redux存储状态变化(我们稍后讨论Redux)。无状态组件的例子就是BicyclesList.js中的自行车列表。这个组件通过props接受一个来自CitiesContainer组件的城市列表,它本身与状态没有任何关系。
React中的路由
由于单页应用中不会重新加载完整的页面,因此产生的问题之一就是路由如何进行。Web应用程序中路由的作用是,在用户访问特定网页时确定需要执行什么。我们的单页应用中只有一个视图,因此没办法像Rails应用程序那样在用户点击链接时跳转到另一个视图。
凡事都有解决的办法,对于这个问题,我们可以使用react-router库。它有许多功能,其中包括:
URL显示用户的当前位置,而不仅仅是显示根页面的URL用户可以使用浏览器的前进和后退按钮用户可以在地址栏中输入URL,跳转到指定页面下面以CitiesContainer为例来介绍路由的工作方式:
App.jsimportReactfromreact;import{Route}fromreact-router-dom;importCitiesContainerfrom./containers/CitiesContainer;classCitiesContainerextendsReact.Component{render(){return(Routepath=/cities