快速学习JavaScript MV *框架的关键是将其分解为一系列功能。 MV *应用程序的主要功能是路由,数据绑定,模板/视图,模型和数据访问。 在本文中,我将描述这些功能,并为每个功能显示AngularJS,Backbone和Ember的代码示例。 您将开始具体地理解这些框架正在试图帮助您完成哪些工作,并认识到它们之间的相似性大于差异。 实际上,很明显,大多数框架都大量借鉴了其他框架的成功。
不要太在意理解每一行代码。 现在,尝试了解它们的相似性以及它们可以为您的项目解决的问题。
路由
路由至少将您的URL映射到一个函数,但有时甚至可以实现用于在视图中管理状态转换的完整“状态机”设计模式。 如果您曾经在服务器端MVC框架(例如Rails,CodeIgniter,CakePHP,ASP.NET MVC等)中使用过路由器,那么您可以将JavaScript MV *路由器视为同一事物,但可以在JavaScript中的客户端。
您可能想知道这是如何工作的,并且在旧版浏览器上是否可以工作? 但是,如果配置了HTML推送状态支持(在大多数框架中使用一行代码),则将URL中的hash标记后的所有内容都视为路由,那么将在客户端上拦截没有哈希的与路由匹配的URL,并运行JavaScript也一样
足够的细节让我们看一些代码。
骨干示例
这是Backbone.js中路由的简单示例:
注意AppRouter
对象。 路由映射到功能。 这些函数仅创建一个视图对象即可管理DOM片段,并在URL更改时将其添加到页面中。 Backbone.history.start()
告诉Backbone开始侦听URL更改。
AngularJS示例
这是AngularJS中路由的简单示例:
AngularJS示例与Backbone示例非常相似,只是路由映射到templateUrl
和控制器函数。
灰烬的例子
以下是在Ember中进行路由的简单示例:
同样,除了Ember.js以外,其他非常相似,路由器“资源”对象的第一个参数是routeName
,第二个参数是URL。 这些参数的顺序一开始让我感到困惑,直到有人指出path参数是可选的,并且可以按照惯例(通常与示例中的about页面一样)进行设置。 同样,需要Ember模板才能使此简单的路由示例正常工作,但我将在后面的部分中对其进行详细介绍。 现在,仅需知道模板已放入{{outlet}}
就足够了。
数据绑定
数据绑定允许模型数据中的更改在视图中更新和/或视图中的更改在模型中自动更新,而无需其他代码。 单向数据绑定通常指示模型更改会传播到视图。 双向数据绑定增加了视图更改的功能,可立即将其显示在模型上。 数据绑定消除了开发人员编写的许多样板代码,并使开发人员可以将精力集中在应用程序中的独特问题上。
AngularJS示例
以下是AngularJS中双向数据绑定的简单示例。 在输入字段中键入将在欢迎消息后显示输入的文本。
骨干示例
骨干网没有自动数据绑定功能,但可以手动进行。 在实践中,我发现单向数据绑定在更改模型时更新视图非常有用。 从视图到模型实际用例的数据绑定很少见。
下面是一个简单的示例,其中已实现将代码绑定到两种方式的代码。
总而言之,您将侦听模型上的change事件,并调用视图的render属性来获取模型以更新视图。 类似地,您侦听输入上的keyup
并通过使用jQuery从输入中获取值并将其设置在模型上以使视图更新模型来更改模型。 这个例子应该使您了解需要多少代码才能使数据绑定正常工作。 还值得注意的是,有许多插件添加了对将数据绑定到Backbone的支持。
灰烬的例子
Ember中的数据绑定如下所示:
Ember使用熟悉的Handlebars进行模板制作,但是该框架还包括“输入帮助器”以绑定常见的表单输入字段。 花括号{{
在此示例中替换了输入中的尖括号<
,并且name
属性没有引号,因此帮助程序知道要绑定它。
模板/视图
模板可以是HTML的整个页面,但更常见的是HTML的较小片段,其中包含用于动态数据的数据绑定占位符表达式。 它们的逻辑可以是无逻辑的,即您的视图中应该几乎没有逻辑,而其他逻辑则允许您将JavaScript直接嵌入模板中。 模板可以基于DOM,并且可以使用DOM动态插入动态数据或基于字符串,将HTML视为字符串并替换动态部分。
让我们看一些例子。
AngularJS示例
这是AngularJS中的一个简单模板示例。
您会注意到,这与之前的路由示例非常相似,其中添加了一些数据绑定,以显示模板如何在您的应用程序中提供帮助。 模板全部包含在主HTML文件中的script
标签中,以使该示例易于遵循并在jsfiddle.net中工作,但是在配置$routeProvider
时,可以通过$routeProvider
templateUrl
属性提供有效的文件路径,从而使templateUrl
在AngularJS中位于视图外部$routeProvider
。
在较大规模的应用中,性能是一个问题处理模板的首选方法是连接并注册在角您AngularJS模板$templateCache
在编译时有一个构建任务,如这一个 。
灰烬的例子
以下是Ember中的模板示例。
灰烬路线是一个对象,它告诉模板它应该显示哪个模型。 我认为它是模板和资源(URL)的最基本控制器,其主要工作是加载模型。 如果需要花哨的时间并存储应用程序状态,则需要一个控制器。
骨干示例
现在,让我们看一下Backbone中模板的简单示例。
这是对路由示例的修改,但是现在标记不是在视图对象的template属性中硬编码为HTML,而是在HTML页面中具有id
属性的script
标记内(浏览器会忽略具有它们类型的script标记) (例如文字/范本)无法辨识,因此范本不会显示或执行)。 为了获得模板(HTML片段),我们使用jQuery选择器通过script
标签的id
来找到元素,抓取innerHTML
,然后将HTML分配给视图对象的template属性(只是一个字符串)。
楷模
模型是通常称为业务对象,域对象或实体的客户端版本。 通常,客户端MV *框架中的模型背后的思想是为应用程序中的数据以及应使用该数据封装的任何行为建立一个中心点。 该模型可以与服务器端MVC和jQuery体系结构进行对比,后者的模型数据通常存储在DOM中。 通过建立模型,目标是从DOM中删除该数据和状态,并将其放在可以重用的公共位置。
骨干示例
模型保存数据并将其保留在DOM之外,并发出事件(例如change
,该事件使大量视图做出相应反应并在需要的地方更新用户界面。 这为您提供了一个真实的来源,而不是用户界面。
我已经通过添加一个新模板和查看同一Person模型对象的视图来修改数据绑定示例。 以前,我在运行时声明了Person模型以使事情保持简单,但是现在我将调用添加到Backbone.Model.extend()
来演示如何为模型创建原型,该模型可以反复使用,类似于古典语言课程。 请注意,两个视图如何侦听同一个人模型对象(change事件)并进行自我更新。 通过使用这种单一数据源,可以将对特定DOM元素的大量调用封装在它们自己的整洁视图中,并且一个模型可以为它们提供服务。
AngularJS示例
AngularJS中存在一个模型,即关于应用程序状态的真相的想法,但是Angular允许您使用普通的旧JavaScript对象作为模型,然后将“监视者”添加到视图中数据绑定的任何属性中使用指令ng-model
。 然后,这些观察者会自动警告应用程序的其他部分,这些其他部分都已绑定到同一模型,并且这些DOM元素知道如何进行自我更新。
这是更新的AngularJS数据绑定示例,显示了要更新的视图的两个部分。
资料存取
数据访问与如何获取和保存应用程序数据有关。 通常,框架假定您正在调用返回JSON的API。
AngularJS示例
AngularJS以两种不同的方式处理数据。 首先,在一个非常相似的方式jQuery的提供手动Ajax调用支持$.ajax
通过功能$http
。 另外,如果您的后端是严格的RESTful服务,则AngularJS提供了$resource
类,该类使对RESTful服务的调用极为简洁。
$http
示例
app.factory('myService', function($http) {
return {
getFooOldSchool: function(callback) {
$http.get('foo.json').success(callback);
}
};
});
app.controller('MainCtrl', function($scope, myService) {
myService.getFooOldSchool(function(data) {
$scope.foo = data;
});
});
$resource
示例
//create a todo
var todo1 = new Todo();
todo1.foo = 'bar';
todo1.something = 123;
todo1.$save();
//get and update a todo
var todo2 = Todo.get({id: 123});
todo2.foo += '!';
todo2.$save();
//delete a todo
Todo.$delete({id: 123});
骨干示例
Backbone假定您正在与RESTful API进行交互,但允许您重写一个方法Backbone.sync()
(如果没有)。 您告诉模型资源在服务器上的位置(URL),然后可以调用save()
。
var UserModel = Backbone.Model.extend({
urlRoot: '/user',
defaults: {
name: '',
email: ''
}
});
var user = new Usermodel();
// Notice that we haven't set an `id`
var userDetails = {
name: 'Craig',
email: 'craigmc@funnyant.com'
};
// Because we have not set an `id` the server will call
// POST /user with a payload of {name:'Craig', email: 'craigmc@funnyant.com'}
// The server should save the data and return a response containing the new `id`
user.save(userDetails, {
success: function (user) {
alert(user.toJSON());
}
});
灰烬的例子
Ember拥有Ember Data,从技术上讲,它不是核心框架的一部分,但正在努力提供更强大的数据持久性/数据存储功能。 它提供了许多在服务器端ORM(例如ActiveRecord)中可以找到的功能,但是它是专门为浏览器中JavaScript的独特环境而设计的。 在撰写本文时,Ember Core Team即将发布v1.0,但尚未发布,许多Ember项目在jQuery中仅使用$.ajax
方法,就像在上面的示例中AngularJS使用$http
。
结论
这篇文章按功能细分了JavaScript MV *框架,以深入了解这些框架提供的功能,并使读者认识到它们实际上非常相似。 一旦了解了框架功能以及它们如何组合在一起,就可以快速轻松地学习多个框架并为您的项目找到合适的框架。
From: https://www.sitepoint.com/anatomy-javascript-mv-framework/