使用 AngularJS 写前端的节奏
- 初始化代码目录, angular-seed
- 按照设计,先把首页 index.html 完成
- 在 app/js/app.js 中规划 routing
如何访问后端的 RESTful 接口
使用 ngResource 而不是使用相对原始的 http
如何更好的理解 AngularJS
通过实际交互流程来理解
- 数据录入页
- directives -> HTML 的扩展语义 (例如, ng-model, ng-controller, 以及自定义的)
- controller -> application behavior (例如,点击保存按钮对应的操作) 一般用在 div 上,已 assigns behavior to a scope
- model -> your application data (例如,输入用户名,在 js 代码里处理时,不需要通过 DOM 的方式来获取,直接通过知道的 model 名字获取即可) ngModel is directive that tells Angular to do two-way data binding.
- 数据展示页
- service -> 对后端的 RESTful api 进行操作
- 更底层的采用 $http
- filter -> 过滤需要展示的数据,也可以自定义 filter
module 与 model 不是一回事
- module -> configures the injector
- injector -> assembles your application
- model -> your application data
如何面对 angular-seed 生成的 5 个 js 文件
angular-seed 默认在 app/js 目录下产生了 5 个 js 文件。 - app.js - controllers.js - directives.js - filters.js - services.js
实际上可以写成一个文件
angular.module('myModule', []).
value('a', 123).
factory('a', function() { return 123; }).
directive('directiveName', ...).
filter('filterName', ...);
分成多个文件的原因
The reason for this breakup is that in your tests, it is often necessary to
ignore the initialization code, which tends to be difficult to test. By
putting it into a separate module it can be easily ignored in tests. The tests
can also be more focused by only loading the modules that are relevant to
tests.
通过对比这 5 个文件,可以发现
- 除了 controllers.js 其他 4 个 js 文件都是以 angular.module() 开头
- directives.js -> angular.module("myApp.directives", []).directive();
- filters.js -> angular.module("myApp.filters", []).filter();
- services.js -> angular.module("myApp.services", []).factory();
- app.js -> angular.module("myApp", ["myApp.filters", "myApp.services", "myApp.directives"]).config();
- 可见 myApp.filters, myApp.services, myApp.directives 均是自定义的名字, 若写成一个 js 文件,则可以省去这些自定义的名字
- controllers.js 则是直接 function ControllerName() {}
- 'use strict'; 每个 AngularJS 文件都采用了 JS 的 严格模式
- ControllerName.$inject = []; 用来注册 controller 的依赖关系。可省略,交由 AngularJS 自动分析。还是推荐写上。
例如,
function ControllerName($log) {}
ControllerName.$inject = ["$log"] 就是用到了 log service.
如何注册一个返回常量的 service
可以认为这是一个全局访问的常量, 在 services.js 中定义
angular.module("myApp.services", []).
value("name", "Zhongwei Sun");
辟邪剑谱中最容易被忽视的 Dependency Injection
在 filters.js 以及 directives.js 中可以看到这样的写法
directive("appVersion", ["version", function(version) {}]);
这是一个 Inline Annotation,因为匿名的回调函数不方便通过设置 $inject 属性的方 法来解决依赖,所以采用这样的语法。
再例如,如果要使用 $log
directive("appVersion", ["$log", function($log) {}]);
实际上也可以写成
directive("appVersion", function($log) {});
但是还是推荐写成第一种形式。第一种形式可以称为显式依赖注入,与之对应的就是隐式 依赖注入。隐式依赖注入可以引起的问题:
假如我们需要压缩、混淆我们的代码,这可能会导致参数名称被更改,遇到这种情况的时 候,我们还是需要使用显式声明依赖的方式。
还有一种是 module 间的依赖,例如, 我要使用 ngResource module 中的 $resource:
<script src="lib/angular/angular-resource.js"></script>
ngular.module('phonecatServices', ['ngResource']).
factory('Phone', function($resource){
return $resource('phones/:phoneId.json', {}, {
query: {method:'GET', params:{phoneId:'phones'}, isArray:true}
});
});
参考:
- https://groups.google.com/forum/#!msg/angular/UkXOVU8_3sw/Y3_gxY3DctAJ
- http://docs.angularjs.org/guide/di
- http://www.cnblogs.com/lcllao/archive/2012/10/16.html
AngularJS 这堆 js 文件的加载顺序是否有要求
AngularJS has dependency injection at its core, 小应用不需要考虑加载顺序。
directive 的命名规则
- js 里定义:directive 在定义的时候采用 ngModel 的形式
- html 里使用:ng-model
参考:
- http://blog.jdriven.com/2012/10/adding-custom-html-attributes-to-your-angularjs-web-app/
service path
return $resource("/todos/:todoId", {todoId: "@id"}
这里的 /todos 对应的即是根目录
Object # has no method 'push'
对于返回的 json 结构中包含错误码的情况,需要将 query 的 isArray 参数设置为 fasle. 否则会报上面的错误。然后在 controller 中对结果进行解析。
service action 什么时候需要加 $ 前缀
- HTTP GET "class" actions: Resource.action([parameters], [success], [error])
- non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
- non-GET instance actions: instance.$action([parameters], [success], [error])
save, remove, delete 需要加 $ 前缀,但是只是在实例化的情况下。若是直接使用类的 delete 则不需要加此前缀。
使用 Masonry + AngularJS 实现瀑布流
代码示例:
- http://jsfiddle.net/kstep/j25aj/9/
- http://jsfiddle.net/pjstarifa/uj98n/2/
AngularUI 与 Bootstrap UI 的区别
- AngularUI 是用 AngularJS 写的一些小功能组件,例如 date picker
- Bootstrap UI 则是使用 AngularJS 将 Bootstrap 的逻辑重写实现了一遍
使用 AngularJS 的输入框验证
<form class="form" novalidate>
<input type="text" required />
</form>
首先需要禁用掉浏览器自带的 form 验证,即使用 novalidate. 原因是,不同浏览器的 行为有差异。比如,chrome 对标记了 required 的输入框,在输入为空的情况下,自动 进行了提示。但是,其他浏览器就没有该行为,比如 safari. 所以需要使用统一的验证 方式。
controller getting invoked twice problem
问题,controller 里的逻辑执行了两次。
原因,controller 在 routing 以及 partial html 里定义了两次。
解决方法,去掉 partial 里的 ng-control 定义.
参考:
- https://groups.google.com/forum/#!topic/angular/yU5cvFKpdE4
AngularJS 需要注意的问题
- service 中不要定义 delete 方法, delete 由于是 js 的关键字,会造成 IE 下的不兼容,完全编译不了
- 需要进行浏览器兼容性测试(手动,自动)
- 使用 jslint 检测代码问题
- 做法是不使用 delete, 用 remove 替代
- https://groups.google.com/forum/?fromgroups=#!topic/angular/W0R6KKfv8QE
- partial view 中的 google ad 无法显示
- 放到 index.html 中
- https://groups.google.com/forum/?fromgroups=#!topic/angular/EyoYWZmsa3o
- Cross-site request forgery:跨站请求伪造 CSRF
- http://stackoverflow.com/questions/14109927/angular-js-verify-csrf-token-in-post-request
- 使用 ng-repeat 做双向绑定时,若结果集是随时更新,最好使用 array, 而不是 map
- 因为 map 默认不是双向绑定的
当N个 HTTP 请求需要顺序处理时,如何避免回调写法
- Javascript Promise 为什么这么迷人
- Understanding JavaScript Object Creation Patterns
- http://docs.angularjs.org/api/ng.$http#methods_jsonp
对 ng-view 的 PV 统计
参考:
ng-cloak
The ngCloak directive is used to prevent the Angular html template from being briefly displayed by the browser in its raw (uncompiled) form while your application is loading. Use this directive to avoid the undesirable flicker effect caused by the html template display.
ng-bind
It is preferrable to use ngBind instead of {{ expression }} when a template is momentarily displayed by the browser in its raw state before Angular compiles it. Since ngBind is an element attribute, it makes the bindings invisible to the user while the page is loading.
参考
- FAQ
- API
- 采用 AngularJS 的 app
- AngularUI
- Bootstrap UI
- AngularJS + Bootstrap 的界面设计参考
- Cheat Sheet
- Angular Pickadate
相关推荐
总的来说,通过 AngularJS 的自定义指令,我们可以将 ECharts 2 的柱状图封装成一个易于复用和维护的组件,使得在页面中多次调用柱状图变得更加便捷和高效。同时,这也展示了 AngularJS 如何优雅地结合第三方库,...
脏检查机制用于检测模型的变化,当模型的值在两次循环之间发生改变时,AngularJS会执行关联的函数。观察者则允许你监听模型的变化,当模型的某个属性改变时,注册的回调函数会被调用。例如: ```javascript $scope....
在AngularJS中,数据绑定主要分为两大类:双向数据绑定和单向数据绑定。双向数据绑定通过指令如ng-model实现,而单向数据绑定则通过{{ }}插值表达式来实现。接下来我们将详细探讨AngularJS中的数据绑定原理。 ### ...
- 编译完成后,AngularJS会立即调用生成的`publicLinkFn`函数,以确保所有指令及其相关的处理逻辑都被正确执行。 #### 三、总结 AngularJS的启动过程是复杂的但又是有序的,从检查环境是否准备妥当到实际的DOM...
内联过滤器会导致模型在 `$digest` 循环中执行两次,影响性能。推荐将过滤器移到控制器或服务中,使用 `$filter` 服务来调用过滤器函数,如: ```javascript var filteredArray = $filter('filter')(array, ...
一、$watch简单使用 $watch是一个scope函数,用于监听模型变化,当你的模型...listener:当watchExpression变化时会被调用的函数或者表达式,它接收3个参数:newValue(新值), oldValue(旧值), scope(作用域的引用) objec
### 构建自己的AngularJS:深入理解Scopes与Digest机制 ...综上所述,AngularJS的核心在于Scopes和Digest机制,通过深入理解这两个概念,开发者可以更好地控制数据流和应用状态,从而构建出更加健壮和高效的Web应用。
- **触发上下文**: 当在 AngularJS 应用之外(比如在浏览器的定时器或异步请求中)改变了模型数据时,需要手动调用 `$apply()` 来触发 AngularJS 的脏检查机制。 - **应用场景**: - 在 `$timeout` 或 `$interval` ...
该方法接受三个参数:要重复执行的函数、两次执行之间的延迟时间(以毫秒为单位)、重复次数。如果需要无限次循环执行,可以将重复次数参数设置为-1。 示例代码如下: ```javascript $interval(function() { //...
5. 避免在模板中使用内联过滤器:内联过滤器会导致模型在$digest中运行两次,影响性能。推荐使用$filter服务在后台调用过滤器,例如:`$filter('filter')(array, expression, comparator)`,这样可以提高性能。 ...
`$setValidity`方法用于设置自定义验证状态,如果两次输入的密码值不匹配,则将`equal`验证状态设置为`false`,反之则为`true`。这样,就可以控制提交按钮的可用状态了。 ### 具体实现步骤 - **方法一的实现步骤**...
- 第二种使用`setInterval`,由于它不在AngularJS的上下文中,因此需要在每次更新后调用`$scope.$apply`来触发脏检查。 总结来说,`$apply`、`$digest`和`$watch`在AngularJS中构建了一个强大的数据绑定系统,确保...
但是用户需要进行两次操作,一次是生成URL,一次是下载文件。尽管操作了两次,但实际只发起了一个HTTP请求,不会对性能产生影响。 第三种方法是先生成Excel文件并存储到服务器,然后再执行下载。这种方法需要涉及到...
文档还提到,为了避免在参数变化时触发两次后端请求,开发者应该将`currentPage`和`itemsPerPage`参数组合为一个字符串,然后通过一个`$watch`来监控。 调用分页插件的示例代码展示了如何在AngularJS应用中集成`tm-...
原因有两点: 1. **可复用性**:自定义指令可以被多次使用,适用于多个场景,而不用在每个需要的地方重复编写相似的事件处理逻辑。 2. **封装性**:自定义指令将事件处理逻辑封装在指令内部,减少了对控制器`$scope...
4. `()">再玩一次</button>`: 这个按钮用于重置游戏,调用`reset()`函数。 5. `ng-if`指令用于条件渲染,根据`$scope.fil`的值来决定哪个提示信息应该显示。 6. `js代码`部分定义了`myCtrl`控制器。在这个控制器中...
在进行页面跳转时,AngularJs应用往往使用$state.go()方法来更改当前路由,这将触发$locationChangeStart和$locationChangeSuccess事件,这两个事件分别对应路由开始变化和结束变化。在$rootScope上监听这两个事件,...
AngularJS提供了两种主要的定时器服务:$interval和$timeout。以下将详细介绍AngularJS中如何使用这两种定时器以及如何正确地移除定时器。 一、$interval服务 $interval服务可以创建一个定时器,定时执行函数。它...
最后,我们使用`$interval`服务来启动倒计时,参数分别为:执行的函数(`countdown`)、执行间隔(1000毫秒,即1秒)和重复次数(100,这里实际上只执行一次,因为我们希望在倒计时结束后停止)。 在AngularJS中,`...