为了降低前端代码的数量,提高可维护性,可测试性,学习了下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. Android布局中实现圆角边框

    设置corners_bg.xml 设置边框圆角可以在drawable-mdpi目录里定义一个xml: <?xml version="1.0" encoding="u ...

  2. Unity3d利用opencv保存游戏视频

    脚本MyVideoWriter.cs using UnityEngine; using System.Collections; using OpenCvSharp; using OpenCvSharp ...

  3. MYSQL常用内置函数详解说明

    函数中可以将字段名当作变量来用,变量的值就是该列对应的所有值:在整理98在线字典数据时(http://zidian.98zw.com/),有这要一个需求,想从多音字duoyinzi字段值提取第一个拼音 ...

  4. MacDev.Mach-O.Programming-Part-III:MachOView-v2.4.9200.dmg-crash

    MachOView-v2.4.9200.dmg Crash 在OS X(其版本号: 10.11.6 (15G31))下载MachOView-2.4.9200.dmg后,打开Fat Binary后,Ma ...

  5. 【如何快速的开发一个完整的iOS直播app】(采集篇)

    原文转自:袁峥Seemygo    感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,首先需要采集主 ...

  6. some things

    ////html[1]/body[1]/div[9]/div[1]/div[1]/div[1]/ul/li  截取规则 Articles/Article[1]:选取属于Articles子元素的第一个A ...

  7. 在 Linux 下将 PNG 和 JPG 批量互转的四种方法

    计算机术语中,批处理指的是用一个非交互式的程序来执行一序列的任务[1]的方法.这篇教程里,我们会使用 Linux 命令行工具,并提供 4 种简单的处理方式来把一些 .PNG 格式的图像批量转换成 .J ...

  8. C#数据结构选择

    选择一个合适的数据结构会对程序的性能有着显著的提高 线性表和链表: 1.LinkedList<T>:适合于元素数组不固定,存在大量列表的头尾添加动作场合.其它可使用List<T> ...

  9. Socket通信基本原理

    Http通信: http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据. Socket通信: Socket通信则是在双方建立起连接后就 ...

  10. UIScrollView

    1.PPT介绍什么是UIScrollView 2.新建项目“大图片展示” * 尽量用storyboard,减少代码 * 设置contentSize属性 * 取消autolayout * 说明frame ...