为了降低前端代码的数量,提高可维护性,可测试性,学习了下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. Java中List,ArrayList、Vector,map,HashTable,HashMap区别用法

    Java中List,ArrayList.Vector,map,HashTable,HashMap区别用法 标签: vectorhashmaplistjavaiteratorinteger ArrayL ...

  2. Unity3d 着色器语法(Shader)

    Shader "name" { [Properties] Subshaders [Fallback] } 定义了一个着色器.着色器拥有一个 Properties 的列表.着色器包含 ...

  3. 初学 react | redux

    react | redux 一.安装 React Redux 依赖 React 0.14或更新版本 npm install --sava react-redux 你需要使用 npm 作为包管理工具,配 ...

  4. SikuliLibrary 库关键字注释

    在  https://github.com/rainmanwy/robotframework-SikuliLibrary 看到rainmanwy 整理的SikuliLibrary库,非常适合工作需要, ...

  5. 复制mueclipse项目到eclipse

    本文适用于将MyEclipse上的项目projectA检出后重命名为projectB的情况,如果只是检出projectA到Eclipse,也可以部分参考 1.从svn上检出Myeclipse项目到Ec ...

  6. MYSQL使用mysqldump导出某个表的部分数据

    命令格式如下: mysqldump -u用户名 -p密码 数据库名 表名 --where="筛选条件" > 导出文件路径 例子: 从meteo数据库的sdata表中导出sen ...

  7. 接微软技术(c#,.net,vb.net, asp.net, sql server, bi, dw etc)项目

    最近闲赋在家,接微软技术的项目,主要有c#,.net,vb.net, asp.net, sql server, bi, dw etc,欢迎推荐.不好意思,借首页发一下.

  8. 其他浏览器(firefox,chrome)可以上网 ie(Internet Explorer)无法上网 解决方法

    http://blog.csdn.net/andywangcn/article/details/8945366

  9. C++基础知识易错点总结(1)

    1. 在C++中,不能被重载的运算符有: sizeof . 成员运算符 .* 成员指针运算符 :: 作用域运算符 ?: 条件运算符 2. C++语言多态性:编译时多态和运行时多态: 编译时多态可通过函 ...

  10. hdoj 1002 A+B(2)

    Problem Description I have a very simple problem for you. Given two integers A and B, your job is to ...