GVKun编程网logo

AngularJS 最佳实践(angularjs项目实战)

8

在本文中,您将会了解到关于AngularJS最佳实践的新资讯,同时我们还将为您解释angularjs项目实战的相关在本文中,我们将带你探索AngularJS最佳实践的奥秘,分析angularjs项目实

在本文中,您将会了解到关于AngularJS 最佳实践的新资讯,同时我们还将为您解释angularjs项目实战的相关在本文中,我们将带你探索AngularJS 最佳实践的奥秘,分析angularjs项目实战的特点,并给出一些关于AngularJS Java EE Web应用程序的基本示例和最佳实践、angularjs – Angular中的身份验证和授权的最佳实践,而不破坏RESTful原则?、angularjs – Firebase / AngularFire中的数据建模最佳实践、angularjs – RestAngular的最佳实践的实用技巧。

本文目录一览:

AngularJS 最佳实践(angularjs项目实战)

AngularJS 最佳实践(angularjs项目实战)

AngularJS 是一个 Web 应用框架,它实现了前端的 MVC 架构,能让开发人员很方便地实现业务逻辑。

举个栗子,要做到下面的效果,以前可能需要写一连串的 JavaScript 代码绑定 N 多事件。而使用 AngularJS 框架,一句 JavaScript 都不用写就能实现了,神奇吧?

angularjs-demo

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script> <div data-ng-app> 单价: <input type="number" min=0 ng-model="price" ng-init="price = 299"> <br> 数量: <input type="number" min=0 ng-model="quantity" ng-init="quantity = 1"> <br> 总价: {{ quantity * price }} </div>

这得益于 AngularJS 中的双向数据绑定特性(Two Way Data-Binding),将 Model 和 View 自动关联了起来,在更复杂的业务场景下,还有代码分离的好处,将 DOM 操作和应用逻辑解耦,非常实用。

不过没有银弹,和其他框架一样,AngularJS 也有它的局限。CRUD 类型的操作是它所擅长的,想想看以前写过的管理后台,几乎大部分都是从数据库中读取数据,然后呈现在页面上,进行各种增删改查。AngularJS 约定了一套规范(约定优于配置),于是你可以很便捷地操作数据。而在其他方面,例如开发复杂的 Web 游戏,AngularJS 则是无用武之地了。

一、AngularJS 中的精美特性

双向绑定

上面的例子已经说明了,我们可以像 PHP Smarty 模板一样在 HTML 中写表达式,用 {{ 和 }} 包起来。在 AngularJS 里,View 和 Model 是在 Controller 里面绑定的,所以无论你在 View 的表单中修改了内容,还是在 Controller 里通过代码修改了 Model 值,两边都会即时发生变化,同步更新。因为 AngularJS 会监控 (watch) Model 对象的变化,随时反映到 View 中。

Filter

Filter 类似 Unix 里面的 | 管道概念,AngularJS 把它搬到了前端。还是举个例子,你们感受一下——

<div>{{ 9999 | number }}</div> <div>{{ 9999+1 | number:2 }}</div> <div>{{ 9*9 | currency }}</div> <div>{{ ''Hello World'' | uppercase }}</div>

输出结果:

9,999
10,000.00
$81.00
HELLO WORLD

二、AngularJS 中的一些“坑”

由于过去写 JavaScript 的习惯使然,人们很容易掉进一些 AngularJS 的陷阱里。下面的内容假设你已经了解前端 MVC 概念,并对 AngularJS 有了一定经验,初学者读起来可能比较艰深晦涩。

DOM 操作

避免使用 jQuery 来操作 DOM,包括增加元素节点,移除元素节点,获取元素内容,隐藏或显示元素。你应该使用 directives 来实现这些动作,有必要的话你还要编写自己的 directives。

如果你感到很难改变习惯,那么考虑从你的网页中移除 jQuery 吧。真的,AngularJS 中的 $http 服务非常强大,基本可以替代 jQuery 的 ajax 函数,而且 AngularJS 内嵌了 jQLite —— 它内部实现的一个 jQuery 子集,包含了常用的 jQuery DOM 操作方法,事件绑定等等。但这并不是说用了AngularJS 就不能用 jQuery 了。如果你的网页有载入 jQuery 那么 AngularJS 会优先采用你的 jQuery,否则它会 fall back 到 jQLite。

需要自己编写 directives 的情况通常是当你使用了第三方的 jQuery 插件。因为插件在 AngularJS 之外对表单值进行更改,并不能即时反应到 Model 中。例如我们用得比较多的 jQueryUI datepicker 插件,当你选中一个日期后,插件会将日期字符串填到 input 输入框中。View 改变了,却并没有更新 Model,因为$(''.datepicker'').datepicker(); 这段代码不属于 AngularJS 的管理范围。我们需要编写一个directive 来让 DOM 的改变即时更新到 Model 里。

var directives = angular.module(''directives'', []);  
directives.directive(''datepicker'', function() { return function(scope, element, attrs) { element.datepicker({ inline: true, dateFormat: ''dd.mm.yy'', onSelect: function(dateText) { var modelPath = $(this).attr(''ng-model''); putObject(modelPath, scope, dateText); scope.$apply(); } }); } });

然后在 HTML 中引入这个 direcitve

<input type="text" datepicker ng-model="myObject.myDateValue" />

说白了 directive 就是在 HTML 里写自定义的标签属性,达到插件的作用。这种声明式的语法扩展了 HTML。

需要说明的是,有一个 AngularUI 项目提供了大量的 directive 给我们使用,包括 Bootstrap 框架中的插件以及基于 jQuery 的其他很热门的 UI 组件。我之前说过 AngularJS 的社区很活跃嘛,生态系统健全。

ngOption 中的 value

这是个大坑。如果你去查看 ngOption 生成的 <select> 中的 <option> 的选项值(每个 <option value="xxx"> 的 value 部分),那绝对是枉费心机。因为这里的值永远都会是 AngularJS 内部元素的索引,并不是你所指定的表单选项值。

还是要转变观念,AngularJS 已经不再用表单进行数据交互了,而是用 Model。使用 $http 来提交 Model,在 php 中则使用 file_get_contents(''php://input'') 来获取前端提交的数据。

{{ }} 的问题

在页面初始化的时候,用户可能会看到 {{ }},然后闪烁一下才出现真正的内容。
解决办法:

  1. 使用 ng-cloak directive 来隐藏它
  2. 使用 ng-bind 替代 {{ }}

将界面与业务逻辑分离

Controller 不应该直接引用 DOM,而应该控制 view 的行为。例如“如果用户操作了 X,应该发生什么事情”,“我从哪里可以获得 X?”

Service 在大部分情况下也不应该直接引用 DOM,它应该是一个单例(singletons),独立于界面,与 view 的逻辑无关。它的角色只是“做 X 操作”。

DOM 操作应该放在 directives 里面。

尽量复用已有功能

你所写的功能很可能 AngularJS 已经实现了,有一些代码是可以抽象出来复用的,使用更 Angular 的方式。总之就是很多 jQuery 的繁琐代码可以被替代。

1. ng-repeat

ng-repeat 很有用。当 Ajax 从服务器获得数据后,我们经常使用 jQuery (比如上面讲过的例子) 向某些 HTML 容器节点中添加更多的元素,这在 AngularJS 里是不好的做法。有了 ng-repeat 一切就变得非常简单了。在你的 $scope 中定义一个数组 (model) 来保存从服务器拉取的数据,然后使用 ng-repeat 将它与 DOM 绑定即可。下面的例子初始化定义了 friends 这个 model

<div ng-init="friends = [{name:''John'', age:25}, {name:''Mary'', age:28}]"> I have {{friends.length}} friends. They are: <ul> <li ng-repeat="friend in friends"> [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. </li> </ul> </div>

显示结果

I have 2 friends. They are:
  [1] John who is 25 years old.
  [2] Mary who is 28 years old.

2. ng-show

ng-show 也很有用。使用 jQuery 来根据条件控制界面元素的显示隐藏,这很常见。但是 Angular 有更好的方式来做到这一点。ng-show (以及 ng-hide) 可以根据布尔表达式来决定隐藏和显示。在 $scope 中定义一个变量:

<div ng-show="!loggedIn"> 点击 <a href="#/login">这里</a> 登录 </div>

类似的内置 directives 还有 ng-disabled, ng-switch 等等,用于条件控制,语法简洁,都很强大。

3. ng-class

ng-class 用于条件性地给元素添加 class,以前我们也经常用 jQuery 来实现。Angular 中的 ng-class 当然更好用了,例子:

<div ng-class="{ errorClass: isError, warningClass: isWarning, okClass: !isError && !isWarning }">...</div>

在这里 ng-class 接受一个 object 对象,key 为 CSS class 名,值为 $scope 变量控制的条件表达式,其他类似的内置 directives 还有 ng-class-even 和 ng-class-odd,很实用。

$watch 和 $apply

AngularJS 的双向数据绑定是最令人兴奋的特性了,然而它也不是全能的魔法,在某些情况下你需要做一些小小的修正。

当你使用 ng-model, ng-repeat 等等来绑定一个元素的值时, AngularJS 为那个值创建了一个 $watch,只要这个值在 AngularJS 的范围内有任何改变,所有的地方都会同步更新。而你在写自定义的 directive 时,你需要定义你自己的 $watch 来实现这种自动同步。

有时候你在代码中改变了 model 的值,view 却没有更新,这在自定义事件绑定中经常遇到。这时你就需要手动调用 scope.$apply() 来触发界面更新。上面 datepicker 的例子已经说明了这一点。第三方插件可能会有 call back,我们也可以把回调函数写成匿名函数作为参数传入$apply()中。

将 ng-repeat 和其他 directives 结合起来

ng-repeat 很有用,不过它和 DOM 绑定了,很难在同一个元素上使用其他 directives (比如 ng-show, ng-controller 等等)。

如果你想对整个循环使用某个 directive,你可以在 repeat 外再包一层父元素把 directive 写在那儿;如果你想对循环内部的每一个元素使用某个 directive,那么把它放到 ng-repeat 的一个子节点上即可。

Scope

Scope 在 templates 模板中应该是 read-only 的,而在 controller 里应该是 write-only 的。Scope 的目的是引用 model,而不是成为 model。model 就是我们定义的 JavaScript 对象。

$rootScope 是可以用的,不过很可能被滥用

Scopes 在 AngularJS 中形成一定的层级关系,树状结构必然有一个根节点。通常我们用不到它,因为几乎每个 view 都有一个 controller 以及相对应的自己的 scope。

但偶尔有一些数据我们希望全局应用在整个 app 中,这时我们可以将数据注入 $rootScope。因为其他 scope 都会继承 root scope,所以那些注入的数据对于 ng-show 这类 directive 都是可用的,就像是在本地 $scope 中的变量一样。

当然,全局变量是邪恶的,你必须很小心地使用 $rootScope。特别是不要用于代码,而仅仅用于注入数据。如果你非常希望在 $rootScope 写一个函数,那最好把它写到 service 里,这样只有用到的时候它才会被注入,测试起来也方便些。

相反,如果一个函数的功能仅仅是存储和返回一些数据,就不要把它创建成一个 service。

三、AngularJS 项目的目录结构

怎样组织代码文件和目录?这恐怕是初学者一开始就会遇到的问题。AngularJS 应用开发的官方入门项目angular-seed,其文件结构是这样的:

  • css/
  • img/
  • js/
    • app.js
    • controllers.js
    • directives.js
    • filters.js
    • services.js
  • lib/
  • partials/

这种结构对于一个简单的单页 app 来说是可行的,只是一旦代码中存在多个 Controller 或者 Service,就很难找到想要寻找的对象了。我们可以对文件按照业务逻辑进行拆分,就像下面这样:

  • controllers/
    • LoginController.js
    • RegistrationController.js
    • ProductDetailController.js
    • SearchResultsController.js
  • directives.js
  • filters.js
  • models/
    • CartModel.js
    • ProductModel.js
    • SearchResultsModel.js
    • UserModel.js
  • services/
    • CartService.js
    • UserService.js
    • ProductService.js

这种结构把不同的业务功能拆分为独立的文件,条理清晰,但是仍有一定的局限性。最大的问题是一个业务功能的代码分布在controllers, models, servers 三个不同目录下,要从中挑出正确的文件,建立起代码关联,还是有些麻烦。按照功能进行模块化划分目录结构,应该要更为合理一些:

  • cart/
    • CartModel.js
    • CartService.js
  • common/
    • directives.js
    • filters.js
  • product/
    • search/
      • SearchResultsController.js
      • SearchResultsModel.js
    • ProductDetailController.js
    • ProductModel.js
    • ProductService.js
  • user/
    • LoginController.js
    • RegistrationController.js
    • UserModel.js
    • UserService.js

这样也是适合 RequireJS 等模块加载器的自然直观的代码组织方式。

转自:http://www.lovelucy.info/angularjs-best-practices.html

AngularJS Java EE Web应用程序的基本示例和最佳实践

AngularJS Java EE Web应用程序的基本示例和最佳实践

如果任何人在Java EE Web应用程序中使用AngularJS,那么我们将非常感谢您能否提供任何指针/示例。

什么是最佳实践,什么是理想的结构,设计等。
任何网络链接也将是有帮助的。

因为这是一个非常一般的问题,我会回答它。在jFall 2012上有一个演讲,演示了使用Java EE 6和AngularJS的一个非常基本的应用程序,可以在这里找到: https://github.com/teunh/jfall2012

我一直在一个学校项目,使用AngularJS作为前端 – JAX-RS作为休息接口和基本的后端逻辑在bean和数据库持久性与hibernate。我现在无法开源这个项目,因为它仍然是一个正在进行中的工作。

我的经验和我给你的信息是,如果你保持一个安静的接口,构建一个Java EE后端与AngularJS前端很容易。

angularjs – Angular中的身份验证和授权的最佳实践,而不破坏RESTful原则?

angularjs – Angular中的身份验证和授权的最佳实践,而不破坏RESTful原则?

长时间风扇,第一次海报:)

我已经阅读了很多有关认证和授权的SO线程与REST和Angular,但我仍然不觉得我有一个伟大的解决方案,我希望做的。对于一些背景,我打算在AngularJS中构建一个我想要支持的应用程序:

>有限的客人访问
>一旦验证,基于角色的访问应用程序
>通过API进行身份验证

所有对REST API的调用都需要通过SSL发生。我想做的是构建应用程序而不破坏RESTful原则,即不保持会话状态存储在服务器上。当然,无论在客户端的授权做什么都必须在服务器端加强。因为我们需要通过每个请求传递整个状态,我知道我需要传递某种令牌,以便接收REST请求的后端服务器可以验证和授权调用。

话说,我的主要问题是关于身份验证 – 这里的最佳做法是什么?看来有很多不同的方法讨论,这里只是一些我发现:

> http://broadcast.oreilly.com/2009/12/principles-for-standardized-rest-authentication.html
> http://frederiknakstad.com/2013/01/21/authentication-in-single-page-applications-with-angular-js/
> http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html

还有一个类似的问题(AngularJS best practice application authentication),但除非我误解了答案,这似乎暗示应该使用服务器会话,这是破坏RESTful原则。

我对Amazon AWS和George Reese文章的主要关注点似乎是假定消费者是一个程序,而不是一个最终用户。可以事先向程序员发出共享秘密,然后谁可以使用它来对这里的呼叫进行编码。这里不是这种情况 – 我需要从应用程序代表用户调用REST API。

这种方法足够吗?假设我有一个会话资源:

POST / api / session

为用户创建新会话

要创建会话,您需要POST一个包含“username”和“password”的JSON对象。

{
    "email" : "austen@example.com","password" : "password"
}

卷曲示例

curl -v -X POST --data '{"username":"austen@example.com","password":"password"}' "https://app.example.com/api/session" --header "Content-Type:application/json"

响应

HTTP/1.1 201 Created {
    "session": {
        "id":"520138ccfa4634be08000000","expires":"2014-03-20T17:56:28+0000"
    }
}

状态代码

> 201 – 创建新会话
> 400 – 错误请求,JSON对象无效或缺少必需的信息
> 401 – 未经授权,请检查电子邮件/密码组合
> 403 – 访问被拒绝,禁用的帐户或许可证无效

为了清楚起见,我省略了HATEOAS的详细信息。在后端,将创建与用户相关联的新的有限持续时间会话密钥。在后续请求中,我可以将其作为HTTP标头的一部分传递:

Authorization: MyScheme 520138ccfa4634be08000000

然后,后端服务器将负责从请求中消化出来,找到相关联的用户并强制执行请求的授权规则。它应该也更新会话的过期。

如果所有这一切都发生在SSL上,我是否可以开放任何类型的攻击,我应该防范?您可以尝试猜测会话密钥并将其放置在标题中,所以我想我可以附加一个用户GUID到会话密钥,以进一步防止暴力攻击。

这是几年来,我积极编程,我只是回到这里的秋千。道歉,如果我是钝的或不必要的重塑轮子,只是希望社区这里运行我的想法,基于我的阅读,到目前为止,看看他们是否通过了石蕊的测试。感谢您提供任何帮助/建议!

当有人询问REST认证时,我推荐使用Amazon Web Services,并基本上建议“这样做”。为什么?因为,从“人群的智慧”的角度来看,AWS解决了这个问题,被大量使用,大量分析和审查的人知道和关心比大多数最安全的请求。安全是一个“不重复轮子”的好地方。在“站在肩上”,你可以做得比AWS差。

现在,AWS不使用令牌技术,而是使用基于共享秘密和有效载荷的安全散列。它可以说是一个更复杂的实现(与所有的规范化过程等)。

但它的工作。

缺点是,它要求您的应用程序保留人共享秘密(即密码),它还要求服务器访问该密码的纯文本版本。这通常意味着密码被加密存储,然后适当地解密。并且邀请更多的复杂性的密钥管理和其他事情在服务器端vs安全散列技术。

最大的问题,当然,与任何令牌传递技术是人在中间的攻击,和重放攻击。 SSL自然地减轻了这些。

当然,你也应该考虑OAuth家族,它们有自己的问题,特别是互操作性,但如果这不是一个主要目标,那么这些技术肯定是有效的。

对于你的应用程序,令牌租赁不是一件大事。您的申请仍然需要在租赁期内运营,或者能够续租。为了做到这一点,它将需要保留用户凭据或重新提示他们。只是将令牌作为第一类资源,像任何其他。如果可行,尝试并与请求关联一些其他信息,并将其捆绑到令牌(浏览器签名,IP地址),只是强制执行一些地方。

您仍然可以接受(潜在的)重放问题,其中相同的请求可以发送两次。对于典型的哈希实现,时间戳是签名的一部分,可以包括请求的生命周期。这在这种情况下解决不同。例如,每个请求可以使用序列ID或GUID发送,您可以记录请求已经播放,以防止它再次发生。不同的技术。

angularjs – Firebase / AngularFire中的数据建模最佳实践

angularjs – Firebase / AngularFire中的数据建模最佳实践

我是第一次在Firebase中开发一个应用程序,并且很好奇我应该如何在两个对象(用户和帖子)之间建模数据.我来自更多的关系数据库背景,不仅好奇这是如何在非关系数据库中完成的,而且特别是如何在Firebase中设置两个对象之间的关系.

例如,我的应用程序有很多用户,每个用户创建许多帖子.

User {
    firstName: String,lastname: String,userName: String
}

Post {
    title: String,content: String,date: Date,writtenBy: [User object?]
}

我应该如何在Firebase中构建这两个对象,以便帖子属于用户,但是无论用户如何都可以查询所有帖子,并且可以在不中断其他对象的数据和/或关系的情况下编辑用户和帖子对象?

我应该如何通过firebase创建新的“关系”对象:

sync.$set({userA: {
   firstname: "Billy",lastName: "Bob",userName: "BillyBob",Posts: {
       // .....
   }
}
});

谢谢!

解决方法

Firebase的构建充分考虑了性能.这就是你必须以不同方式设计数据结构的原因,在大多数情况下,规范化是你的敌人. Firebase中的每个对象都可以通过URL访问,您应该始终牢记这一点.
设计数据结构的方法仍然很多,这取决于您要执行哪些查询.如果其中一个查询能够显示所有消息(我相信一些最新消息将是最常见的用例),但同时您希望能够显示每个用户的消息而不是一个可能的消息数据结构可能如下所示:

User {
    userId(assigned by Firebase automatically) {
        firstName: String,userName: String
    }
}

Post {
    User {
        userId(matching userId in the User object) {
            postId(assigned by Firebase for every new post automatically) {
                title: String,writtenBy: String,userName or userId (this is not really needed,but may keep it for easier data access)
            }
        }
    }
}

然后,您可以更改任何用户数据,而不会触发帖子中的数据更改事件,例如您的示例中(如果您有大量邮件,这将非常繁重).
您可以独立于用户获取所有消息:

var postListRef = new Firebase(URL);
var lastPostQuery = postListRef.child("Post").limit(500);

你也可以使用startAt()和endAt()问题https://www.firebase.com/docs/web/api/query/limit.html
作为一个缺点 – 如果你只需要显示消息,你必须在for循环中解压缩每条消息,但我希望你也会显示用户信息,所以它应该没问题.

如果您只想收听一条用户消息,那么它非常简单快捷:

var postListRef = new Firebase(URL);
var lastPostQuery = postListRef.child("Post/User").child(userId);

Angular / AngularFire对这种数据结构有很大的支持.

angularjs – RestAngular的最佳实践

angularjs – RestAngular的最佳实践

所以我开始研究一个自己的项目,我正在开发我的网站的前端.我开始使用 PHP Laravel后端,并为我的数据库设置了一个API服务.

考虑到混合应用程序,我开始在我的前端Web应用程序中使用angularjs.为了使用REST与我的API进行通信,我遇到了restangular,这非常好,因为它正是我所希望的.

只有一个困扰我的问题,没有真正的“指南”如何设置可维护的模块/工厂/提供者/服务来复制您的api系统将数据存储在本地存储或设置简单系统,您可以注入将“模型”转换为控制器,然后执行Model-> getAll()来获取所有模型.

因为我是angularJS的新手,因此我对如何解读这个问题的了解非常有限.到目前为止,我已经做到了这一点:

主要应用

var client = angular.module('clientApp',['angulartics','angulartics.google.analytics','ngRoute','restangular']);

client.config(['$routeProvider',function($routeProvider){
    $routeProvider
        .when('/',{
            controller: 'flongsController',templateUrl: '/client_partials/Homepage.html'
        })
        .when('/flongs/:slug',templateUrl: 'client_partials/Flong.html'
        })
        .otherwise({
            redirectTo: '/'
        });
}]);

flongsController

client.controller('flongsController',['$scope','Restangular','$routeParams',function ($scope,Restangular,$routeParams) {
    //controller variables
    var baseFlongs = Restangular.all('flongs');

    $scope.flongs = {};

    init();

    function init() {
        baseFlongs.getList().then(function(flongs){
            $scope.flongs = flongs;
        });
    }

}]);

所以,我的问题很简单:

如何改进此代码以使其更高效,更易于维护?

提前致谢,
Nick van der Meij

解决方法

首先,不要在控制器上使用服务逻辑,而是使用角度服务来实现此目的.

让我分享一下我如何构建我的项目,

首先构建Restangular服务:

angular.module('example').factory('exampleService',['Restangular',function(Restangular){

    // this is service object with list of methods in it
    // this object will be used by controller
    var service = {
        getExamples: getExamples,getExample: getExample
    };

    // get examples from server by using Restangular
    function getExamples(){
        return Restangular.all('examples').getList();
    }

    // get example with given id from server by using Restangular
    function getExample(exampleId){
        return Restangular.one('examples',exampleId).get();
    }

    return service;

}]);

现在我们构建exampleService,让它将它注入控制器

angular.controller('ExampleCtrl',['exampleService',function(exampleService){

    // get examples by using exampleService
    exampleService.getExamples().then(function (examples) {
        $scope.examples = examples;
    });

    // get example with given id by using exampleService
    exampleService.getExample('1234').then(function (example) {
        $scope.example = example;
    });

}]);

这就是我基本上如何使用它.有关更高级的用法,请查看Restangular Github Page中的示例.

今天的关于AngularJS 最佳实践angularjs项目实战的分享已经结束,谢谢您的关注,如果想了解更多关于AngularJS Java EE Web应用程序的基本示例和最佳实践、angularjs – Angular中的身份验证和授权的最佳实践,而不破坏RESTful原则?、angularjs – Firebase / AngularFire中的数据建模最佳实践、angularjs – RestAngular的最佳实践的相关知识,请在本站进行查询。

本文标签: