我记得当我开始构建Web应用程序时,我曾经严重依赖于后端框架来满足大多数模板需求。 (一开始)用Jinja或刀片脚本简单地填充我的页面以创建功能性的用户界面非常具有诱惑力。 因为那时我对MVC的了解非常有限,所以这花费了我可维护的代码。
我碰到了一本非常有趣的书,其中讨论了创建单页应用程序的最佳实践,您可以在这里找到。 我认为只是我的核心逻辑的副产品的视图层还需要更多的东西,即自己的MVC! 规则几乎相同。 但是必须记住,模型,视图和控制器的复杂性取决于要求。 对于每页GitHub动作之类的界面而言,其相对而言低于Gmail或Canva的界面,对于交互性较低的应用程序,与具有丰富UI的应用程序,管理服务器的调用有所不同。 因此,事先熟悉设计很重要,这种理念有利于react的开发,因为react鼓励您将DOM元素视为独立的组件。
事不宜迟,让我们讨论一下文件在我们应用中的排列方式。
成份股
让我们讨论一下SPA的不同方面,并对其进行分解。 让我们先看看它们是什么,我们将在下一节中将它们连接起来。
资料层
与其他应用程序一样,SPA中的模型也处理项目的数据层,它负责进行API调用,以获取数据并使用JSON响应来填充模型,因为react没有任何正式的定义模型的方法,我选择为此使用骨架JS 。 这也免除了定义自己的数据源的麻烦。
主干JS中有两个用于有效管理数据的类:Model和Collection类。
该模型
模型是BackboneJS中数据的绝对表示。 以下是基本模型的摘要。
import Backbone from 'backbone';
const Property = Backbone.Model.extend({
urlRoot : Constants.api_url+'/api/property'
});
export default Property;
这是Property.js文件中的代码,它是一个Backbone 模型 ,我们可以调整其属性以设置验证器,设置默认值等。但是最重要的是,我们将使用它从API中获取数据。 我们的模型将通过jqXHR请求获取数据,我们要做的就是为我们的API指定有效的URL。
馆藏
集合用于管理模型集。 模型仅表示该数据类型的单个实体,如果您的API返回属性列表,该怎么办?
import Backbone from 'backbone';
import Property from '../models/Property';
var PropertyCollection = Backbone.Collection.extend({
model: Property,
initialize: function(models, options) {
this.data = options.data;
},
url: function(){
return Constants.api_url;
},
parse: function(data) {
return data;
}
});
export default PropertyCollection;
上面的代码位于PropertyCollection.js中,您可以看到我们使用我们先前声明的Property模型初始化了'model'属性。 如果您的REST API遵循正确的约定,它会自动配置 CURD请求,则您只需使用.create().fetch()和.destroy()方法即可。
查看+控制器
对于那些想知道为什么我将这两部分混在一起的人,我有一个问题。 SPA的最终目的是什么? 提供UI! 毕竟这只是一个更复杂的视图层。 如果您要进行大量的客户端计算,则使用单独的控制器将很有意义。 但是,对于大多数应用程序而言,唯一需要关注的是提供一个无缝界面,并且要解决此问题,视图就成了繁重的工作! 阅读这出为”你的意识。
然而,在反应的情况下,取消控制器就更有意义了,因为每个组件都有自己的呈现和生命周期方法。 其中几乎涵盖了您需要的所有计算。
在开始编写视图之前,您必须分析最终用户应用程序的设计。 仔细看一下您将要服务的页面的设计,并仔细观察层次结构。 例如看这个例子。
假设这是您要构建的APP的页面。 在顶层,您可以使用Body ,它封装了您要显示的所有内容。 这将是您的第一个React组件。 然后在单独的文件中一一创建子组件。
import React from 'react';
import Header from '../widgets/Header';
import Title from '../widgets/Title';
import Footer from '../widgets/Footer';
import PropertyDetail from '../widgets/PropertyDetail'
const SinglePage = ({match}) => {
return(
<div id="wrapper" className="clearfix">
<Header></Header>
<Title></Title>
<PropertyDetail property_id={match.params.id}></PropertyDetail>
<Footer></Footer>
</div>
)
}
export default SinglePage;
这是我制作的应用程序中的线框之类的顶级组件,例如Body ,其中Header , Title , PropertyDetail和Footer都是顶级包装程序的子级。 甚至PropertyDetail也有自己的子代,依此类推。
以后,所有顶级组件均作为应用程序的独立页面
现在让我们讨论一下线框。 尽管我们知道Body可以作为我们应用程序的页面,但是对于Featured Content或Posts却不能说相同,它们将成为我们应用程序的小部件,在大多数情况下,这些小部件将利用我们之前讨论的模型。
路线
现在,对于路由,我们将使用大多数人都听说过的React路由器。 但是在此之前,让我们先讨论一下URL。 SPA中的URL是应用程序特定状态的表示,即,与路线和参数一起可以将APP加载到所需状态。 在交互式SPA中,每个页面具有多个状态是很正常的,您希望通过URL访问应用程序的多个状态,但这意味着URL方案混乱,因此最好兼顾两者。
为了制作干净的URL,我决定将它们保存在单独的文件中(而不使用动态 URL😄),以获得熟悉的MVC感觉。 使用React Router定义的路由仅是JSX标签,组件作为道具传递给它们。
<Router>
<div>
<Route exact path="/search/:keyword" component={ListPage}/>
<Route exact path="/property/:id" component={SinglePage}/>
</div>
</Router>
这里的ListPage和SinglePage是我的顶级反应组件。 另请注意,您必须使用<div>标签包装多个URL。
接线
好吧,我们知道什么是超赞的SPA,是时候将它们组合在一起了。 首先使用在Facebook孵化器存储库中找到的create-react-app生成一个项目,这对设置初始项目非常有帮助,并且所有现代Web开发工具都为您管理,因此您可以专注于编写应用程序而不是配置webpack(顺便说一句,值得单独解释一下)。 由于您将要编写模块化代码,因此编写测试要容易得多,因此create-react-app使用Jest运行测试。
生成应用程序后,您的文件夹结构将如下所示。
my-app/
├── package.json
├── package-lock.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
├── README.md
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── registerServiceWorker.js
尝试运行npm start
,如果一切正常,则可以在3000端口上访问您的应用。 还要记住将所有代码放在src目录中,该文件夹之外的任何内容均不可访问,这是create-react-app生成器施加的限制。
重新整理东西
面对现实吧,当前工作目录状态无法实现创建SPA的梦想。 除了index.js和registerServiceWorker.js,我们将所有内容移至新目录。 在触摸任何内容之前,请创建此目录结构。 让脚本保持原样。
my-app/
├── package.json
├── package-lock.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── js
│ └── manifest.json
├── README.md
└── src
├── assets #All the media/styles/fonts/helper_functions:p
│ ├── objects
│ └── styles
├── components #controller+view Layer
│ ├── pages #top-level pages
│ └── widgets #children
├── data #Data Layer
│ ├── collections #Backbone.Collection
│ └── models #Backbone.Model
├── routes #React router routes
├── App.css #unruly mess
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── registerServiceWorker.js #end unruly mess
首先要创建这些东西(不一定按此顺序)
- 在
/src/components/pages
创建一个简单的react组件,称为Home.js - 在中创建Urls.js
/src/Urls
并创建一个指向Home对象的<Route exact path=”/” component={Home}/>
。 当您访问域根目录时,这将呈现Home.js的内容。 - 将index.js中的渲染行更改为
ReactDOM.render(<Urls/>, document.getElementById('root'));
在执行此操作时,请确保每个JavaScript文件仅导出一件事,并确保正确使用import语句。
这里要注意的另一件事是,顶级React页面不能是react类,因为React Router在URL中传递参数,这些URL作为参数而不是props传递!
虽然鼓励您将小部件作为扩展React.component的类。 现在,您可以使用模型将数据传递到小部件或初始化其状态 。
最后,当您准备部署该应用程序时,请运行npm run build
,它将捆绑您的所有资产,将其设置为生产模式,并将打包的项目保存到项目的构建目录中。 您现在可以部署您的应用程序了!
值得一提的是,我很高兴分享我对SPA的看法,这也帮助我整理了有关该主题的想法。
如果您喜欢这篇文章,请随时点击below下面的鼓掌按钮,以帮助其他人找到它!
From: https://hackernoon.com/creating-awesome-spas-with-react-66b4e2043621