在AngularJS负责人Igor Minar
的这篇文章中:
MVC vs MVVM vs MVP 。许多开发人员可能花费数小时来辩论和争论,这是一个有争议的话题。
几年来,AngularJS更加接近于MVC(或其客户端变体之一),但是随着时间的流逝,由于许多重构和api的改进,现在它更加接近 MVVM –
$ scope 对象可以被认为是 ViewModel 。由我们称为 Controller 的函数修饰。能够对框架进行分类并将其放入MV
*存储桶之一具有一些优势。通过使创建代表使用框架构建的应用程序的思维模型更容易,它可以帮助开发人员更熟悉其api。它还可以帮助建立开发人员使用的术语。话虽如此,我宁愿看到开发人员构建经过精心设计并遵循关注点分离的踢屁股应用程序,也不愿看到他们浪费时间争论MV 废话。基于这个原因,我特此声明
AngularJS 为 MVW框架-Model-View-Whatever 。凡代表什么“ 对您有用* ”。Angular为您提供了很大的灵活性,可以很好地将表示逻辑与业务逻辑和表示状态分开。请使用它来提高您的生产力和应用程序可维护性,而不是热烈讨论最后没有什么关系的事情。
在客户端应用程序中实现AngularJS MVW(模型-视图-任何)设计模式是否有任何建议或准则?
感谢大量有价值的资源,我为在AngularJS应用程序中实现组件提供了一些一般性建议:
控制器应该只是模型和视图之间的 中间层 。尝试使其尽可能 薄 。
强烈建议 避免 在控制器中使用 业务逻辑 。应该将其移至模型。
控制器可以使用方法调用(在孩子想与父母进行通信时)或 $ emit , $ broadcast 和 $ on 方法与其他控制器通信。发出和广播的消息应保持最少。
控制器不应该 关心表示 或DOM操作。
尽量 避免嵌套控制器 。在这种情况下,父控制器被解释为模型。而是将模型作为共享服务注入。
*控制器的 *作用域 应用于与视图 绑定* 模型,并像 表示模型 设计模式那样
封装 视图模型 。
*
如治疗范围 只读模板 和 只写在控制器 。范围的目的是引用模型,而不是模型。
在进行双向绑定(ng-model)时,请确保您不直接绑定到范围属性。
AngularJS中的模型是 service* 定义的 单例 。 *
模型提供了分离数据和显示的绝佳方法。
模型是单元测试的主要候选者,因为它们通常仅具有一种依赖关系(某种形式的事件发射器,在通常情况下为 $ rootScope )并且包含高度可测试的
域逻辑 。
模型应被视为特定单元的实现。它基于单一职责原则。单元是一个实例,负责其自身的相关逻辑范围,该逻辑可以表示现实世界中的一个实体,并在编程世界中根据 数据和状态对其进行描述 。
模型应封装您的应用程序数据,并提供 API 以访问和操纵该数据。
模型应该是 便携式的, 以便可以轻松地运输到类似的应用程序。
通过隔离模型中的单元逻辑,您可以更轻松地查找,更新和维护。
模型可以使用整个应用程序通用的更通用的全局模型的方法。
如果不是真正依赖于减少组件耦合并增加单元 可测试性 和 可用性, 请尝试避免使用依赖注入将其他模型组合到模型中。
尝试避免在模型中使用事件侦听器。它使它们更难测试,并且通常会按照单一职责原则杀死模型。
由于模型应在数据和状态方面封装一些逻辑,因此在结构上应限制对其成员的访问,因此我们可以保证松散耦合。
在AngularJS应用程序中执行此操作的方法是使用 工厂
服务类型进行定义。这将使我们能够非常轻松地定义私有属性和方法,并在单个位置返回可公共访问的属性和方法,这将使其对开发人员真正可读。
一个例子 :
angular.module('search')
.factory( 'searchModel', ['searchResource', function (searchResource) {
var itemsPerPage = 10,
currentPage = 1,
totalPages = 0,
allLoaded = false,
searchQuery;
function init(params) {
itemsPerPage = params.itemsPerPage || itemsPerPage;
searchQuery = params.substring || searchQuery;
}
function findItems(page, queryParams) {
searchQuery = queryParams.substring || searchQuery;
return searchResource.fetch(searchQuery, page, itemsPerPage).then( function (results) {
totalPages = results.totalPages;
currentPage = results.currentPage;
allLoaded = totalPages <= currentPage;
return results.list
});
}
function findNext() {
return findItems(currentPage + 1);
}
function isAllLoaded() {
return allLoaded;
}
// return public model API
return {
/**
* @param {Object} params
*/
init: init,
/**
* @param {Number} page
* @param {Object} queryParams
* @return {Object} promise
*/
find: findItems,
/**
* @return {Boolean}
*/
allLoaded: isAllLoaded,
/**
* @return {Object} promise
*/
findNext: findNext
};
});
尽量避免让工厂返回新的有能力的函数,因为这会破坏依赖注入,并且库的行为会很尴尬,尤其是对于第三方。
完成同一件事的更好方法是使用工厂作为API,以返回带有附加的getter和setter方法的对象集合。
angular.module('car')
.factory( 'carModel', ['carResource', function (carResource) {
function Car(data) {
angular.extend(this, data);
}
Car.prototype = {
save: function () {
// TODO: strip irrelevant fields
var carData = //...
return carResource.save(carData);
}
};
function getCarById ( id ) {
return carResource.getById(id).then(function (data) {
return new Car(data);
});
}
// the public API
return {
// ...
findById: getCarById
// ...
};
});
通常,尝试避免这种情况并正确设计模型,以便可以将其注入控制器并在视图中使用。
在特定情况下,某些方法需要应用程序内的全局可访问性。为了使之成为可能,您可以在 $ rootScope中 定义’ common‘属性,并在应用程序引导期间将其绑定到 commonModel :
angular.module('app', ['app.common'])
.config(...)
.run(['$rootScope', 'commonModel', function ($rootScope, commonModel) {
$rootScope.common = 'commonModel';
}]);
您所有的全局方法都将位于“ common ”属性内。这是某种 名称空间 。
但是不要直接在 $ rootScope中
定义任何方法。在视图范围内与ngModel指令一起使用时,这可能导致意外的行为,通常使您的范围乱七八糟,并导致范围方法覆盖问题。
资源使您可以与不同的 数据源进行 交互。
应该使用 single-responsibility-principle实现 。
在特定情况下,它是HTTP / JSON端点的 可重用 代理。
资源被注入模型中,并提供了发送/检索数据的可能性。
工厂创建一个资源对象,使您可以与RESTful服务器端数据源进行交互。
返回的资源对象具有可提供高级行为的操作方法,而无需与低级$ http服务进行交互。
模型和资源都是服务 。
服务是独立的,独立的, 松散耦合 的功能单元。
服务是Angular从服务器端带到客户端Web应用程序的功能,在该服务器上,服务已被长期使用。
Angular应用程序中的服务是可替换对象,这些对象使用依赖项注入连接在一起。
Angular带有不同类型的服务。每个都有自己的用例。有关详细信息,请阅读了解服务类型。
尝试考虑应用程序中服务体系结构的主要原理。
通常根据Web服务词汇表:
服务是一种抽象资源,代表从提供者实体和请求者实体的角度来看,执行形成一致功能的任务的能力。要使用该服务,必须由具体的提供者代理来实现服务。
通常,应用程序的客户端分为 模块 。每个模块都应作为一个单元进行 测试 。
尝试根据 功能/特性 或 视图
(而不是类型)定义模块。有关详细信息,请参见Misko的演示。
按照惯例,模块组件可以按类型分组,例如控制器,模型,视图,过滤器,指令等。
但是模块本身仍然是 可重用 , 可 转让 和 可测试的 。
对于开发人员来说,查找代码的某些部分及其所有依赖性也要容易得多。
有关详细信息,请参阅LargeAngularJS和JavaScript应用程序中的代码组织。
文件夹结构的示例 :
|-- src/
| |-- app/
| | |-- app.js
| | |-- home/
| | | |-- home.js
| | | |-- homeCtrl.js
| | | |-- home.spec.js
| | | |-- home.tpl.html
| | | |-- home.less
| | |-- user/
| | | |-- user.js
| | | |-- userCtrl.js
| | | |-- userModel.js
| | | |-- userResource.js
| | | |-- user.spec.js
| | | |-- user.tpl.html
| | | |-- user.less
| | | |-- create/
| | | | |-- create.js
| | | | |-- createCtrl.js
| | | | |-- create.tpl.html
| |-- common/
| | |-- authentication/
| | | |-- authentication.js
| | | |-- authenticationModel.js
| | | |-- authenticationService.js
| |-- assets/
| | |-- images/
| | | |-- logo.png
| | | |-- user/
| | | | |-- user-icon.png
| | | | |-- user-default-avatar.png
| |-- index.html
angular-app 实现了角度应用程序结构的一个很好的例子 -https ://github.com/angular-app/angular-app/tree/master/client/src
现代应用程序生成器也考虑了这一点-https: //github.com/yeoman/generator-angular/issues/109
能接触到的常见问法: 项目中有用到什么设计模式?(前端更多点) 重构使用了什么设计模式?(如果你项目强调了重构一般会问) 说说对 XX 模式的理解?(个人接触过的是单例和工厂,这两个比较多) 有接触到哪些?实际用到过哪些?(通用) 除了这些,还有一些不常见的进阶和基础问法,这些直接在下面整理 -- 设计模式这个主题还挺玄乎的,个人直观体验是,自己日常实习那段时间问得挺频繁的,可能是因为没啥好问的。
本文向大家介绍谈一谈,你了解的 Java设计模式。相关面试题,主要包含被问及谈一谈,你了解的 Java设计模式。时的应答技巧和注意事项,需要的朋友参考一下 考察点:设计模式 所谓设计模式,就是一套被反复使用的代码设计经验的总结(情境中一个问题经过证实的一个解决方案)。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使人们可以更加简单方便的复用成功的设计和体系结构。
解释器(Interpreter) Intent 为语言创建解释器,通常由语言的语法和语法分析来定义。 Class Diagram TerminalExpression:终结符表达式,每个终结符都需要一个 TerminalExpression。 Context:上下文,包含解释器之外的一些全局信息。 Implementation 以下是一个规则检验器实现,具有 and 和 or 规则,通过规则可以构
本文向大家介绍请说说你了解的设计模式有哪些?相关面试题,主要包含被问及请说说你了解的设计模式有哪些?时的应答技巧和注意事项,需要的朋友参考一下 1、单例模式 在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。保证一个类仅有一个实例,并提供一个该实例的全局访问点。 (1)经典模式--单线程 对于线程来说不安全;但在单线程中已满足要求。
有些人问我,你说学习操作系统的最好办法是学习程序设计。那我们是不是应该学习一些“设计模式”(design patterns)。这是一个我很早就有定论,而且经过实践检验的问题,所以想在这里做一个总结。 总的来说,如果光从字面上讲,程序里总是有一些“模式”可以发掘的。因为你总是可以借鉴以前的经验,来构造新的程序。你可以把这种“经验”叫做“模式”。可是自从《设计模式》(通常叫做 GoF,“Gang
本文向大家介绍javascript设计模式之解释器模式详解,包括了javascript设计模式之解释器模式详解的使用技巧和注意事项,需要的朋友参考一下 神马是“解释器模式”? 先翻开《GOF》看看Definition: 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如何创建一个抽象语