为了降低前端代码的数量,提高可维护性,可测试性,学习了下AngularJS,正在准备投入项目开发中。

AngularJS的概念比较多,如果面向对象方面的书理解的不透的话学习起来有些费劲,它的官方有个快速入门不错,中文版如下

http://www.ituring.com.cn/minibook/303

但除了入门外,要真实的写项目还是得把模块划分,依赖关系处理,组件间通信,文件目录安排等问题解决好才能干活。

根据这个学习目的,写了个DEMO,地址如下

http://onlytiancai.github.io/codesnip/angular-demo1.html

  1. 页面初始化时有3个苹果,3个桔子,用户可以在输入框里重新输入桔子和苹果的数量,界面会有相应的变化
  2. 定义了两个模块
    1. common是通用模块,
      1. 包含一个commonErrorMsg的directive用来显示全局的错误信息, 通过监听common.showerror事件来获取信息,并让字体显示为红色
    2. myApp是整个单页面应用的模块,
      1. 包含inputCtrl, statusCtrl两个controller
      2. 包含fruits, orange, apple三个directive
      3. 包含range的filter
      4. 包含fruitsService的service
  3. 总体依赖关系如下
    1. myApp依赖common
    2. fruits, inputCtrl, statusCtrl都依赖fruitsService
    3. inputCtrl通过事件隐含依赖common
    4. 总体来说上层module依赖底层module,上层controller依赖底层service
  4. fruits是一个自定义的directive,用来显示所有水果
    1. transclude=True表示它的子元素也受它管理,比如里面的时苹果和桔子
    2. 该directive要和inputCtrl进行通信,以便动态更改水果的数量, 所以它和inputCtrl共同依赖fruitsService,并通过fruitsService的事件进行通信。
  5. 事件基本是全局的,所以定义事件时尽量有个命名空间, 如common.showerror, fruitsService.updated
  6. orange和apple是两个很普通的directive,其中apple还掩饰了directive里如何处理自身的UI事件
  7. statusCtrl就监听fruitsService.updated事件,并更新自己的状态
  8. inputCtrl里watch自身UI里的两个ng-model,适时调用fruitsService的相关方法
    1. 如果界面输入太大的数字,会向common.showerror发送消息,以在界面上提示给用户 这里没有用ng-form自带的验证就是为了演示模块间如何通信
  9. range的filter是弥补ng-repeat的不足,让它支持类似 x in range(10)的形式
  10. fruitsService纯粹是为了directive之间或controller之间通信和共享数据所设计

HTML代码

<!doctype html>
<html ng-app="myApp">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="angular.js"></script>
<script src="angular-demo1.js" charset="utf-8"></script>
<title>AngularJS Demo</title>
</head>
<body>
<p common:error_msg></p>
<p ng-controller="statusCtrl">一共有{{apple_count}}个苹果,{{orange_count}}个桔子。</p>
<fruits>
<apple ng-repeat="n in [] | range:apple_count"></apple>
<orange ng-repeat="n in [] | range:orange_count"></orange>
</fruits>
<p ng-controller="inputCtrl">请输入
<input type="text" ng-model="apple_count" />个苹果,
<input type="text" ng-model="orange_count" />个桔子
</p>
</body>
</html>

js代码

angular.module('common', []);
angular.module('common').directive('commonErrorMsg', function(){
return {
restrict: "A",
controller: function ($scope, $element, $attrs) {
$element.css('color', 'red');
$scope.$on('common.showerror', function (ev, msg) {
$element.html(msg);
});
}
}
}); var myApp = angular.module('myApp', ['common']);
myApp.directive('fruits', function(fruitsService) {
return {
restrict: "E",
transclude: true,
replace: true,
template: '<ul ng-transclude></ul>',
controller: function ($scope, $element, $attrs) {
$scope.$on('fruitsService.updated', function () {
$scope.apple_count = fruitsService.apple_count;
$scope.orange_count = fruitsService.orange_count;
});
}
}
})
.directive('orange', function() {
return {
restrict: "E",
template: '<li>桔子</li>'
}
})
.directive('apple', function() {
return {
restrict: "E",
template: '<li><a ng-click="show()" href="#">苹果</a></li>',
link: function(scope, element, attrs) {
scope.show = function(){
alert('我是一个苹果');
};
}
}
})
.controller('statusCtrl', function($scope, fruitsService) {
$scope.$on('fruitsService.updated', function () {
$scope.apple_count = fruitsService.apple_count;
$scope.orange_count = fruitsService.orange_count;
});
})
.controller('inputCtrl', function($scope, fruitsService, $rootScope) {
$scope.$watch('apple_count', function (newVal, oldVal, $scope) {
if (newVal > 10){
$rootScope.$emit('common.showerror', '苹果数量太多了');
}else{
fruitsService.set_apple_count(newVal);
}
}, true);
$scope.$watch('orange_count', function (newVal, oldVal, $scope) {
if (newVal > 10){
$rootScope.$emit('common.showerror', '桔子数量太多了');
}else{
fruitsService.set_orange_count(newVal);
}
}, true);
fruitsService.set_apple_count(3);
fruitsService.set_orange_count(2);
})
.filter('range', function() {
return function(input, total) {
total = parseInt(total);
for (var i=0; i<total; i++)
input.push(i);
return input;
};
})
.service('fruitsService', function ($rootScope) {
this.set_apple_count = function (apple_count) {
this.apple_count = apple_count;
$rootScope.$broadcast('fruitsService.updated');
};
this.set_orange_count = function (orange_count) {
this.orange_count = orange_count;
$rootScope.$broadcast('fruitsService.updated');
};
});

下面这篇帖子也很好,关于如何用AngularJS开发大型项目的。

如何组织大型JavaScript应用中的代码?

蛙蛙推荐:AngularJS学习笔记的更多相关文章

  1. AngularJs学习笔记--Guide教程系列文章索引

    在很久很久以前,一位前辈向我推荐AngularJs.但当时我没有好好学习,仅仅是讲文档浏览了一次.后来觉醒了……于是下定决心好好理解这系列的文档,并意译出来(英文水平不足……不能说是翻译,有些实在是看 ...

  2. AngularJs学习笔记--bootstrap

    AngularJs学习笔记系列第一篇,希望我可以坚持写下去.本文内容主要来自 http://docs.angularjs.org/guide/ 文档的内容,但也加入些许自己的理解与尝试结果. 一.总括 ...

  3. AngularJS学习笔记2——AngularJS的初始化

    本文主要介绍AngularJS的自动初始化以及在必要的适合如何手动初始化. Angular <script> Tag 下面通过一小段代码来介绍推荐的自动初始化过程: <!doctyp ...

  4. AngularJs学习笔记--Modules

    原版地址:http://code.angularjs.org/1.0.2/docs/guide/module 一.什么是Module? 很多应用都有一个用于初始化.加载(wires是这个意思吗?)和启 ...

  5. AngularJs学习笔记--Understanding the Model Component

    原版地址:http://docs.angularjs.org/guide/dev_guide.mvc.understanding_model 在angular文档讨论的上下文中,术语“model”可以 ...

  6. AngularJs学习笔记--Forms

    原版地址:http://code.angularjs.org/1.0.2/docs/guide/forms 控件(input.select.textarea)是用户输入数据的一种方式.Form(表单) ...

  7. AngularJs学习笔记--expression

    原版地址:http://code.angularjs.org/1.0.2/docs/guide/expression 表达式(Expressions)是类Javascript的代码片段,通常放置在绑定 ...

  8. AngularJs学习笔记--directive

    原版地址:http://code.angularjs.org/1.0.2/docs/guide/directive Directive是教HTML玩一些新把戏的途径.在DOM编译期间,directiv ...

  9. AngularJs学习笔记--html compiler

    原文再续,书接上回...依旧参考http://code.angularjs.org/1.0.2/docs/guide/compiler 一.总括 Angular的HTML compiler允许开发者自 ...

  10. AngularJs学习笔记--concepts(概念)

    原版地址:http://code.angularjs.org/1.0.2/docs/guide/concepts 继续.. 一.总括 本文主要是angular组件(components)的概览,并说明 ...

随机推荐

  1. mysql 用命令操作

    本篇文章来源于http://c.biancheng.net/cpp/html/1441.html mysql:连接数据库 mysql命令用户连接数据库. mysql命令格式: mysql -h主机地址 ...

  2. Android开发工具全面转向Android Studio(2)——AS project/module的CRUD

    本文有些地方可能需要衔接Android开发工具全面转向Android Studio(1)——准备开发环境,读起来效果会更好. 这个世界很奇妙,所有的东西离不开CRUD,即增删改查.即使人本身也遵循这个 ...

  3. Merge Intervals 运行比较快

    class Solution { public: static bool cmp(Interval &a,Interval &b) { return a.start<b.star ...

  4. WNDR3700V4 安装SVN Server

    下文所用路由器型号为:WNDR3700V4 参考链接:http://dd-wrt.ca/phpBB2/viewtopic.php?t=86912&highlight=optware http: ...

  5. ubuntu命令大全

    一.文件/文件夹管理 ls 列出当前目录文件(不包括隐含文件) ls -a 列出当前目录文件(包括隐含文件) ls -l 列出当前目录下文件的详细信息 cd .. 回当前目录的上一级目录 cd - 回 ...

  6. linux 定时清理session

    php session 运营想让用户登陆网站就能永久保持登陆会话,感觉这是扯淡,因为视频播放1小时,所以我设置了两小时过期. 但是用户过多,导致session文件大量存储.产生上百万千万.服务器空间很 ...

  7. tomcat连接池配置详解

    <bean class="org.apache.tomcat.jdbc.pool.PoolProperties"> <property name="ur ...

  8. redis五种数据类型的使用(zz)

    redis五种数据类型的使用 redis五种数据类型的使用 (摘自:http://tech.it168.com/a2011/0818/1234/000001234478_all.shtml ) 1.S ...

  9. C#窗口应用如何居中

    在form的属性设置里面有一个初始位置的设置(startposion)设置成centerscreen(屏幕居中即可)

  10. linux系统编程之错误处理机制

    在讲解liunx错误处理机制之前我们先来看一段代码: #include<sys/types.h> #include<sys/stat.h> #include<fcntl. ...