提问者:小点点

大型AngularJS应用程序设计


我需要建议如何设计一个包含多个复杂模块的AngularJS应用程序,并根据用户角色在验证后加载模块

我们已经确定了许多可以跨不同模块重用的指令。在设计阶段,我们已经确定了以下应该存在的问题,并对以下一些问题给出了答案,但我们仍然需要专家的建议:

  • 一个模块可以有
    • 部分 控制器
    • 指令
    • 服务

    应用程序的用户界面看起来像是,页面顶部有一个固定的菜单栏,左上角有一个下拉导航,根据用户的角色有多个链接。当用户点击链接时,相应的模块应该被加载到页面中。必须有一个空项目,该项目是手动引导的,并在运行时加载其他模块。

    我们的方法是采用以下文件夹结构:

    • 应用程序
    • 指令
    • 实体json(例如客户、产品等)
    • 部分

    因此,我的问题是:

    • 模块内的服务如何与其他模块通信?
    • 模块应该独立开发和运行?
    • 如何处理模块之间的通信与传输数据?
    • 如何集成所有上述元素,特别是异常处理,日志记录?
    • 开发者应该了解我们定义的约定?
    • 调用什么方法来记录,在模块之间发送信息?

共3个答案

匿名用户

我建议将yeoman纳入您的工作流程,并为您的项目使用生成器,这将使您构建应用程序的方式更加简单,特别是在团队中工作时。

今年早些时候,angular公司的人发布了一份关于你的应用程序结构最佳实践的文档,我建议你阅读它,据说有一个基于这些最佳实践的生成器,名为cg angular,我完全推荐。

我将引用cg angular网站:

所有子生成器都会提示用户指定保存新文件的位置。因此,您可以创建所需的任何目录结构,包括嵌套。生成器将在项目的根目录中创建少量文件,包括索引。html,应用程序。js和应用程序。较少的您可以确定项目其余部分的结构。

关于你的问题:

  • 模块内的服务如何与其他模块通信?

您可以为指令/和服务/创建一个文件夹,您将在不同的模块中重用。

  • 模块应该独立开发和运行?

你可以在一个应用程序中有几个模块(你可以根据需要加载它们,可能使用requirejs,但这是离题的)

  • 如何处理模块之间的通信与传输数据?

使用服务在不同模块中的控制器之间传递信息

  • 如何集成所有上述元素,特别是异常处理,日志记录?

您可以为所有模块执行通用错误处理程序和通用http侦听器

  • 开发人员应该理解我们定义的约定吗

使用一个生成器,他们是有意见的,他们给出团队所需的顺序和约定。

匿名用户

有很多好问题要问;它们似乎分为两大类——第一类是代码结构问题,第二类是度量(日志等)。

模块内的服务如何与其他模块通信?

理想情况下,您应该为您的模块使用指令。通过这种方式,您可以利用通过要求属性链接控制器的能力。这是一个关于在指令和控制器之间共享数据的页面。

模块是否应独立开发和运行?

我想你正在考虑单元测试。是的,理想情况下,您的模块应该尽可能严格地限定范围,以使测试更容易。

如何通过传输数据处理模块之间的通信?

这是通常使用服务的地方。注意:在AngularJS中,服务、工厂和提供者的意思都是一样的,只是它们的声明方式略有不同。挑一个你觉得最舒服的。

如何集成上述所有元素,特别是异常处理、日志记录?

日志记录是另一个问题。AngularJS的美妙之处在于,您可以非常轻松地扩充框架的现有部分,以便添加您认为合适的功能或行为。您可以使用装饰器来完成此操作。这里是一个异常日志的例子,我认为它将涵盖您可能感兴趣的任何用例

开发者应该了解我们定义的约定?

对此的答案总是相同的:沟通是他们如何知道的。开发人员需要将公约社会化,否则你永远不会得到认可。

调用什么方法进行日志记录,在模块之间发送信息?

上面回答。

匿名用户

大型AngularJS和JavaScript应用程序中的代码组织

一旦应用程序的规模增大,许多开发人员就很难组织它的代码库。我最近在AngularJS和JavaScript应用程序中看到了这一点,但从历史上看,这是所有技术中的一个问题,包括我过去研究过的许多Java和Flex应用程序。

总的趋势是沉迷于按类型组织事物。它与人们整理衣服的方式极为相似。

地板上的桩

让我们来看看角种子,AngularJS应用程序的正式起点。“应用程序”目录包含以下结构:

css/img/js/app。js控制器。js指令。js过滤器。js服务。js lib/partials/JavaScript目录为我们编写的每种类型的对象都有一个文件。这很像把你的衣服在地板上整理成不同的堆。你有一堆袜子、内衣、衬衫、裤子等等。你知道你的黑色羊毛袜子就在角落里的那堆里,但要把它们挖出来需要一段时间。

这简直是一团糟。人们不应该这样生活,开发人员也不应该这样编码。一旦你超过了大约六个控制器或服务,这些文件就变得笨拙了:你要找的对象很难找到,源代码控制中的文件更改集变得不透明,等等。

袜子抽屉

组织JavaScript的下一个逻辑步骤是为一些原型创建一个目录,并将对象拆分为它们自己的文件。为了延续服装的比喻,我们现在投资了一个漂亮的莫哈霍尼梳妆台,计划把袜子放在一个抽屉里,内衣放在另一个抽屉里,把裤子和衬衫整齐地叠在其他抽屉里。

让我们设想一下,我们正在构建一个简单的电子商务站点,其中包含登录流、产品目录和购物车用户界面。我们还为模型(业务逻辑和状态)和服务(HTTP/JSONendpoint代理)定义了新的原型,而不是将它们归为Angular的单一“服务”原型。我们的JavaScript目录现在可以如下所示:

控制器/LoginController.js注册Controller.js产品详细ontroller.js搜索结果Controller.jsdirectives.jsfilters.js型号/CartModel.js产品odel.js搜索结果Model.js用户odel.js服务/CartService.js用户ervice.js产品ervice.js不错!对象现在可以通过浏览文件树或使用IDE快捷方式轻松定位,源代码控制中的更改集现在可以清楚地指示修改了什么,等等。这是一个重大的改进,但仍然受到一些限制。

想象一下,你在办公室,意识到明天早上出差需要干洗几套衣服。你打电话回家,让你的另一半把你的黑木炭和蓝色细条纹西装送到洗衣店。别忘了灰色衬衫配黑色佩斯利领带和白色衬衫配纯色黄色领带。想象一下,你们的另一半完全不熟悉你们的梳妆台和衣橱。当他们仔细检查你的领带抽屉时,他们看到了三条黄色的领带。选哪一个?

如果你的衣服是按服装组织的,那不是很好吗?虽然在现实世界中,成本和空间等实际约束使得服装很难做到这一点,但类似的事情也可以通过零成本代码实现。

模块化

希望陈腐的隐喻不会太乏味,但以下是总结:

你的另一半是团队中的新开发人员,他被要求修复你应用程序中众多屏幕之一的错误。开发人员在目录结构中进行筛选,看到所有控制器、模型和服务组织得井井有条。不幸的是,它并没有告诉他/她哪些对象是相关的或相互依赖的。如果开发人员希望在某个时候重用某些代码,他们需要从一堆不同的文件夹中收集文件,并且总是会忘记其他文件夹中的代码。信不信由你,在你正在构建的新报告应用程序中,你很少需要重用电子商务应用程序中的所有控制器。但是,您可能需要重用某些身份验证逻辑。如果这一切都在一个地方不是很好吗?让我们根据功能区域重新组织应用程序:

购物车/购物车模型。js CartService。js通用/指令。js过滤器。js产品/搜索/搜索结果控制器。JSSearchResultsModel。js ProductDetailController。jsproductmodel。js产品服务。js用户/登录控制器。js注册控制器。js用户模型。js用户服务。js任何随机开发人员现在都可以打开顶级文件夹,并立即了解应用程序的功能。同一文件夹中的对象具有关系,有些对象将依赖于其他对象。了解登录和注册过程的工作原理与浏览该文件夹中的文件一样简单。通过复制/粘贴实现的原语重用至少可以通过将文件夹复制到另一个项目中来实现。

使用AngularJS,我们可以更进一步,创建一个相关代码的模块:

1 2 3 4 5 6 7 8 9 10 11 12 13变量用户模块=角度。模块('userModule',[]);用户模块。工厂('userService',['$http',函数($http){returnnewuserservice($http);}])
用户模块。工厂('userModel',['userService',函数(userService){返回新的userModel(userService);}])
用户模块。控制器('loginController',['$scope','userModel',loginController]);用户模块。控制器('registrationController',['$scope','userModel',registrationController]);查看rawUserModule。js托管于❤ 通过GitHub,如果我们随后放置UserModule。js进入用户文件夹,它将成为该模块中使用的对象的“清单”。这也是为RequireJS或Browserify添加一些加载程序指令的合理位置。

常见代码提示

每个应用程序都有许多模块使用的通用代码。我们只需要一个地方,它可以是一个名为“公共”或“共享”或任何你喜欢的文件夹。在真正大型的应用程序中,功能和交叉关注点往往有很多重叠。这可以通过以下几项技术进行管理:

如果模块的对象需要直接访问几个“公共”对象,请为它们编写一个或多个外观。这有助于减少每个对象的协作者数量,因为协作者过多通常是一种代码气味。如果您的“通用”模块变大,请将其细分为解决特定功能区域或问题的子模块。确保您的应用程序模块只使用它们需要的“通用”模块。这是“界面分离原理”与固体分离原理的变体。将实用程序方法添加到$rootScope上,以便子作用域可以使用它们。这有助于避免将相同的依赖项(如“PermissionsModel”)连接到应用程序中的每个控制器。请注意,这应该谨慎地进行,以避免弄乱全局范围并使依赖关系不明显。使用事件将两个不需要彼此显式引用的组件解耦。AngularJS通过Scope对象上的$emit、$broadcast和$on方法实现了这一点。控制器可以触发事件以执行某些操作,然后收到操作已完成的通知。关于资产和测试的简要说明

我认为在组织HTML、CSS和图像方面有更多的灵活性。将它们放在模块的“assets”子文件夹中可能会在封装模块的资产依赖项和不太混乱之间取得最佳平衡。不过,我认为为该内容单独设置一个顶级文件夹,其中包含一个反映应用程序包结构的文件夹结构也是合理的。我认为它也适用于测试。

请看下面的链接,

https://blog.safaribooksonline.com/2014/03/27/13-step-guide-angularjs-modularization/