angularJS学习笔记(二)

前言

首先,了解 一下ng的一些概念:

  • module 代码的组织单元,其它东西都是定义在具体的模块中的。
  • app 应用业务,需要多个模块的配合完成。
  • service 仅在数据层面实现特定业务功能的代码封装
  • controller 与DOM结构相关联的东西,即是一种业务封装概念,又体现了项目组织的层级结构
  • filter 改变数据的一种机制
  • directive 与DOM结构相关联,特定功能的封装形式

上面的这些概念基本上就是ng的全部。每一部分都可以自由定义,使用时通过各种要素的相互配合来实现我们的业务需求。

模块(module)

每个ng应用都默认加载一个模块“ng”,该组件内部提供了一些常用的功能,我们可以直接使用使用他们,但这些功能可能没法完成我们的需求。因此ng另外还封装了一些其它模块,如ngAnimate、ngResource、ngRoute等,这些模块分别提供了一些各不相同的功能,注入进来我们就可以完全使用他们。我们也可以通过angular.module来创造、注册和加载模块。

一个模块是 一组服务,指令,控制器,过滤函数和配置信息的集合。

angular.module

我们可以通过angular.module(name, [requires], [configFn])创造一个模块。模块名是绑定到模板中ngApp值,requires是需要依赖加载的模块,configFn是requires加载完成之后的初始化工作。返回一个带有其它方法和属性的模块。

  • provider() $provide.provider()的引用
  • factory() $provide.factory()的引用
  • service() $provide.service()的引用
  • value() $provide.value()的引用
  • constant() $provide.constant()的引用
  • decorator() $provide.decorator()的引用
  • animation() 自定义动画指令,$animateProvider.register()的引用
  • filter() 自定义过滤指令,$filterProvider.register()的引用
  • controller() 自定义控制器,$controllerProvider.register()的引用
  • directive() 自定义指令,$compileProvider.directive()的引用
  • config() 配置函数
  • run() 应用初始化
  • name 模块名
  • requires 依赖模块数组

自定义服务$provide

当你想在当前模块的控制器去引用另一模板的控制器功能时,可以自定义一个相关服务,然后在需要该服务的控制器中显示声明依赖该服务,这样就可在多个控制器中使用同一段逻辑代码。

ng提供服务的过程涉及它的依赖注入机制。而provide服务内置一些使用injector注册服务的方法。

(1)provider方法:注册一个服务提供函数。

该函数是一个构造函数,通过内部的$get属性来提供一个服务。

    var fn = function() {
        this.$get = function() {
            return "china";
        };
    }

    var myApp = angular.module(‘myApp‘, [], function($provide) {
        $provide.provider(‘test‘, fn);
    });

    myApp.controller(‘myCtrl‘, function($scope, test) {
        console.log(test);
    });

上面是一种定义服务的方法,不常用,而且我也没搞懂,汗。。。

(2)factory方法

是provider方法的简写,相当于provider(name, {get:getFn}),直接把一个函数成是一个对象的get()方法,这样就不用显示地定义一个provider方法了。(3)service方法注册一个服务实例,和factory方法功能相似。区别是factory直接传进get方法即可,而service方法传入的是一个构造函数。即service返回的是一个对象,而factory方法 可以是一个数字或字符串。例如ng入门实例中的phonecat程序内部定义的ajax服务使用的就是factory方法,返回请求的json字符串。

phonecatServices.factory(‘Phone‘, [‘$resource‘,
  function($resource){
    return $resource(‘phones/:phoneId.json‘, {}, {
      query: {method:‘GET‘, params:{phoneId:‘phones‘}, isArray:true}
    });
  }]);

(3)value方法

相当于provider方法中的$get属性函数不需要参数且直接返回值的情况。provider方法中的test服务例子可直接简写:

myApp.value(‘test‘,"China");

传入值可以是字符串、数字、数组、对象和函数。

(4)constant方法

和value方法功能类似,即给一个服务名绑定一个常量,该常量可以是字符串、数字、数组、对象和函数。区别就是通过constant方法注册的服务能够被注入进module的配置中,而且不能被decorator方法修改。

(5)decorator(name, decorator)方法

中断一个服务的初始化,修改这个服务。参数name是已经定义但需要被修改的服务名。

var myApp = angular.module(‘myApp‘, [])
            .config([‘test‘, function(test) {
                        console.log(test.name);
            }])
            .constant(‘test‘,{name:"constant"})
            .value(‘valueTest‘,{name:‘value‘})
            .decorator(‘valueTest‘, function() {
                return {
                    name: ‘decoration‘
                };
            })
            .controller(‘myCtrl‘, [‘valueTest‘, function(valueTest) {
                console.log(valueTest.name);
            }]);

自定义指令directive

通过前面的学习,我们慢慢发现,ng中的功能都是通过在相应模板中绑定功能的指令来完成。如

<div ng-controller="Controller">
  Hello <input ng-model=‘name‘> <hr/>
  <span ng-bind="name"></span> <br/>
  <span ng:bind="name"></span> <br/>
  <span ng_bind="name"></span> <br/>
  <span data-ng-bind="name"></span> <br/>
  <span x-ng-bind="name"></span> <br/>
</div>

而ng的指令绑定方式有element names,attributes,comment,class names

<my-dir></my-dir>
<span my-dir="exp"></span>
<!-- directive: my-dir exp -->
<span class="my-dir: exp;"></span>

ng不仅提供了一些简单的指令供我们使用,同时也允许我们自定义指令。通过模块中的directiveAPI可以定义指令,而最简单的定义指令方式是直接返回一个函数:

angular.module(‘myApp‘, [])
.directive(‘myLink‘, function($interval, dateFilter) {
                    return function link(scope, element, attrs) {
                        var format,
                                timeoutId;

                        function updateTime() {
                            element.text(dateFilter(new Date(), format));
                        }

                        scope.$watch(attrs.myLink, function(value) {
                            format = value;
                            updateTime();
                        });

                        // 注册$destoty事件,防止内存泄露问题
                        // 当编译的DOM被销毁时触发
                        element.on(‘$destroy‘, function() {
                            $interval.cancel(timeoutId);
                        });

                        // start the UI update process; save the timeoutId for canceling
                        timeoutId = $interval(function() {
                            updateTime(); // update DOM
                        }, 1000);
                    }
                });

指令名必须是驼峰格式的命名,而直接直接返回函数的形式等同于复杂指令定义方式中的返回link函数

angular.module(‘myApp‘, [])
                .directive(‘myCurrentTime‘, function($interval, dateFilter) {

                    function link(scope, element, attrs) {
                        var format,
                                timeoutId;

                        function updateTime() {
                            element.text(dateFilter(new Date(), format));
                        }

                        scope.$watch(attrs.myCurrentTime, function(value) {
                            format = value;
                            updateTime();
                        });

                        // 注册$destoty事件,防止内存泄露问题
                        // 当编译的DOM被销毁时触发
                        element.on(‘$destroy‘, function() {
                            $interval.cancel(timeoutId);
                        });

                        // start the UI update process; save the timeoutId for canceling
                        timeoutId = $interval(function() {
                            updateTime(); // update DOM
                        }, 1000);
                    }

                    return {
                        link: link
                    };
                });

即定义指令的复杂形式是返回一个对象,对象含有以下几种可能用到的属性:

  • multiElement
  • priority
  • terminal
  • scope
  • controller
  • require
  • restrict
  • templateNamespace
  • template
  • templateUrl
  • replace(ng2.0中会被移除)
  • transclude
  • compile
  • link

在定义复杂的指令形式之前,我们必须了解一下ng对指令的解析和执行过程:

  • 浏览器将得到的HTML字符串内容解析成DOM结构
  • ng引入,将DOM结构扔给$compile函数处理:
    • $compile遍历DOM匹配指令,将指令添加进匹配DOM元素的指令列表中。一个元素可以匹配多个指令。
    • 关联DOM的多个指令按权重排列
    • 指令指令中的compile函数(可修改DOM结构),返回link函数
    • 得带的所有link函数组成一个列表作为$compile函数的返回
  • 指令link函数(连接模板的scope)

下面是一个复杂指令的定义方式:

myApp.directive(‘directiveName‘, function factory(injectables) {
  var directiveDefinitionObject = {
    priority: 0,
    template: ‘<div></div>‘, // or // function(tElement, tAttrs) { ... },
    // or
    // templateUrl: ‘directive.html‘, // or // function(tElement, tAttrs) { ... },
    transclude: false,
    restrict: ‘A‘,
    templateNamespace: ‘html‘,
    scope: false,
    controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
    controllerAs: ‘stringIdentifier‘,
    bindToController: false,
    require: ‘siblingDirectiveName‘, // or // [‘^parentDirectiveName‘, ‘?optionalDirectiveName‘, ‘?^optionalParent‘],
    compile: function compile(tElement, tAttrs, transclude) {
      return {
        pre: function preLink(scope, iElement, iAttrs, controller) { ... },
        post: function postLink(scope, iElement, iAttrs, controller) { ... }
      }
      // or
      // return function postLink( ... ) { ... }
    },
    // or
    // link: {
    //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },
    //  post: function postLink(scope, iElement, iAttrs, controller) { ... }
    // }
    // or
    // link: function postLink( ... ) { ... }
  };
  return directiveDefinitionObject;
});
  • multiElement

    当该属性设为true时,HTML编译器会搜集在directive-name-enddirective-name-end之间DOM节点,当作一个集合 作为directive elements使用

  • priority

    设置指令的权重,默认为0.当一个DOM元素匹配多个指令时,根据权重的大小来执行相应的指令。

  • terminal

    设为true时,当前指令是指令集中的最后 一个会被执行的指令。任何权重值小于当前指令权重的指令都不会被指令。

  • scope

    true创建一个新的作用域。{ }创建一个 隔离的scope,可引用相关节点属性:”@attr”引用节点属性,”=attr”把节点属性值引用成scope属性值,“&attr”把节点属性值包装成函数

  • controller

    为指令定义一个controller构造函数,允许指令之间彼此通信。function($scope,$element,$attrs,$transclude){}

  • require

    引用其它指令的控制器作为link函数的第四个参数。跟一个字符串或者字符串数组。

    • (no prefix) 在当前元素内查找控制器
    • ?努力查找或者null
    • ^ 在当前元素和父元素内查找
    • ^^ 在元素的父元素内查找
  • restrict

    决定指令的应用方式,默认EA

    • E 节点名“`
    • A 属性名
    • C 类值
    • M 注释
  • templateNamespace

    模板中的标记。html、svg、math

  • template

    模板内容

  • templateUrl

    模板地址取代模板内容

  • replace

    决定模板内容取代的位置,默认false。true:模板取代指令元素.false:模板取代指令元素的内容。

  • transclude

    true或者element

  • compile

    function compile(tElement,tAttrs, transclude) 装换模板内容。

  • link

    仅当compile属性没有定义时,才会使用。funciton link(scope,iElement,iAttrs,controller,transcludeFn)

    ps:暂时也就只能理解这么多。。。

    可以看官方的一个例子:

<!doctype html>
<html lang="en" ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="../js/angular.min.js"></script>
</head>
<body>
    <my-tabs>
        <my-pane title="Hello">
            <h4>Hello1</h4>
            <p>Lorem ipsum dolor sit amet</p>
        </my-pane>
        <my-pane title="World">
            <h4>World1</h4>
            <em>Mauris elementum elementum enim at suscipit.</em>
            <p><a href ng-click="i = i + 1">counter: {{i || 0}}</a></p>
        </my-pane>
    </my-tabs>

    <script>
        angular.module(‘myApp‘, [])
                .directive(‘myTabs‘, function() {
                    return {
                        restrict: ‘E‘,
                        transclude: true,
                        scope: {},
                        controller: function($scope) {
                            var panes = $scope.panes = [];

                            $scope.select = function(pane) {
                                angular.forEach(panes, function(pane) {
                                    pane.selected = false;
                                });
                                pane.selected = true;
                            };

                            this.addPane = function(pane) {
                                if (panes.length === 0) {
                                    $scope.select(pane);
                                }
                                panes.push(pane);
                            };
                        },
                        templateUrl: ‘my-tabs.html‘
                    };
                })
                .directive(‘myPane‘, function() {
                    return {
                        require: ‘^myTabs‘,
                        restrict: ‘E‘,
                        transclude: true,
                        scope: {
                            title: ‘@‘
                        },
                        link: function(scope, element, attrs, tabsCtrl) {
                            tabsCtrl.addPane(scope);
                        },
                        templateUrl: ‘my-pane.html‘
                    };
                });
    </script>
</body>
</html>

my-tabs.html

<div class="tabbable">
    <ul class="nav nav-tabs">
        <li ng-repeat="pane in panes" ng-class="{active:pane.selected}">
            <a href="" ng-click="select(pane)">{{pane.title}}</a>
        </li>
    </ul>
    <div ng-transclude></div>
</div>

my-pane.html

<div class="tabbable">
    <ul class="nav nav-tabs">
        <li ng-repeat="pane in panes" ng-class="{active:pane.selected}">
            <a href="" ng-click="select(pane)">{{pane.title}}</a>
        </li>
    </ul>
    <div ng-transclude></div>
</div>

路由ngRoute

ngRoute模块提供了关于路由方面的一些服务和指令。根据URL中的hash部分发生变化时触发在路由服务中预定义的业务逻辑,例如phonecat应用程序中使用到的路由服务:

phonecatApp.config([‘$routeProvider‘,
  function($routeProvider) {
    $routeProvider.
      when(‘/phones‘, {
        templateUrl: ‘partials/phone-list.html‘,
        controller: ‘PhoneListCtrl‘
      }).
      when(‘/phones/:phoneId‘, {
        templateUrl: ‘partials/phone-detail.html‘,
        controller: ‘PhoneDetailCtrl‘
      }).
      otherwise({
        redirectTo: ‘/phones‘
      });
  }]);

运行时会发现这些url匹配的都是url的hash部分,eg: http://localhost:8000/app/#/phones

加载路由

由于ng将路由部分单独作为一个模块服务定义,因此在使用相关路由服务之前,需加载引用:

<script src="../js/angular.min.js"></script>
<script src="../js/angular-route.min.js"></script>

angular.module(‘myapp‘,[‘ngRoute‘]);

使用

要使用路由功能,需要在相应的模块初始化阶段通过引用routeProvider这个服务来定义:(1)routeProvider.when(path, route)

path参数是将要匹配的路径,可以在路径中定义需要获得的参数,例如“/phones/:phoneId”可以匹配”phones/111”,其中phoneId就是变量,即对应变量前使用”:”匹配。

route是对应路由匹配成功后进行的业务处理对象。包含属性:

  • controller 控制器
  • template 模板内容
  • templateUrl 模板路由
  • resolve 可选需要注入进controller中的依赖,是一个对象,对象的key是依赖注入的名,value是string或function
  • redirectTo 重定义到新路由

(2)$routeProvider.otherwise(params)

当以上定义的路由都没有匹配时使用。

(3)ngView

HTML模板指令,当相关路由匹配成功时对应的模板内容加载区域。<div ng-view></div>

(4)routeParams服务路由中的参数对象。键名为路径中定义的参数名。需要提前加载。仅当路由完全改变后对应的routeParams对象才更新。但我们可使用route.current.params来访问新的路由参数。(5)route 控制路由匹配的controllers和views,监控$location.url的变化然后匹配。

  • reload() 重新加载
  • updateParams(newParams) 使用新的路由参数更新当前路由
  • $routeChangesStart 路由改变前的事件
  • $routeChangeSuccess 路由成功改变事件
  • $routeChangeError 路由改变错误事件
  • current 应用当前路由的定义
  • routes 当前路由的默认对象
<div ng-controller="MainController">
  Choose:
  <a href="Book/Moby">Moby</a> |
  <a href="Book/Moby/ch/1">Moby: Ch1</a> |
  <a href="Book/Gatsby">Gatsby</a> |
  <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
  <a href="Book/Scarlet">Scarlet Letter</a><br/>

  <div ng-view></div>

  <hr />

  <pre>$location.path() = {{$location.path()}}</pre>
  <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
  <pre>$route.current.params = {{$route.current.params}}</pre>
  <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
  <pre>$routeParams = {{$routeParams}}</pre>
</div>

另外,$location是ng中默认提供的一个服务:

- absUrl() 当前绝对路径

- url([url]) 更改或获取路径

- protocol() 当前路径协议

- host()

- port()

- path([path])

- search(search,[paramValue])

- hash([hash])

ngResource

ngResource与ngRoute一样,单独的模板,需要提前加载。

ngResource是AJAX服务的一种更高级,抽象的服务,底层仍然调用AJAX服务,该模块是通过$resource提供了和服务端RESTful接口交互支持的服务。

$resource(url, [paramDefaults], [actions], options)

一个创建可以和RESTful服务端交互的resource对象的工厂函数。

  • url 可以含有参数
  • paramDefaults 默认的url参数值,可以在actions里面被重写
  • actions 自定义的方法列表,扩展默认的方法
  • options 用户自定义设置
    • stripTrailingSlashes 默认为true,省略任何计算的URL后面的斜杠。
phonecatServices.factory(‘Phone‘, [‘$resource‘,
  function($resource){
    return $resource(‘phones/:phoneId.json‘, {}, {
      query: {method:‘GET‘, params:{phoneId:‘phones‘}, isArray:true}
    });
  }]);

ng还提供了一些其它的模块和服务,总之ng在真的很强大,它打破了我们以往按照jQuery+CSS+HTML开发动态网站的思维,将我们带入了另一个全新的世界。


参考

http://www.zouyesheng.com/angular.html

http://www.cnblogs.com/lcllao/archive/2012/10/18/2728787.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 23:26:14

angularJS学习笔记(二)的相关文章

angularjs 学习笔记(二) ----- bootstrap框架

1.  下载新的jquery-1.11.1文件. 2.  下载新的bootstrap文件. 3.  选择流式布局的模板填充入index.html文件. 4.  将top.foot转为nginclude文件 nginclude必须使用$scope对象,因此需要设置一个全局的mainctrl来将字符串或全局变量注入$cope中. $rootScope.global =global; 直接将全局变量global赋值给$rootScope,并且之后的子$Scope会获得继承,静态定义与ctrl分开. 5

AngularJS 学习笔记二

AngularJS指令 指令 描述 讲解 ng_app 定义应用程序的根元素. 指令 ng_bind 绑定 HTML 元素到应用程序数据. 简介 ng_click 定义元素被单击时的行为. HTML 事件 ng_controller 为应用程序定义控制器对象. 控制器 ng_disabled 绑定应用程序数据到 HTML 的 disabled 属性. HTML DOM ng_init 为应用程序定义初始值. 指令 ng_model 绑定应用程序数据到 HTML 元素. 指令 ng_repeat

AngularJS学习笔记二

指令 1.restrict:指令声明四种表现形式:A(属性).C(类).E(元素).M(注释),使用“restrict”来进行配置. 2.template:指令中生成的字符串html模版 3.templateUrl:模版的地址 4.replace:将原指令所在标签替换为模版内容时,是否保存原指令html,为false时则将模版中内容插入原指令标签中. 5.transclude:将原指令中间的内容移动到template中有“ng-transclude”指令所属标签位置,为true时,覆盖模版中标签

AngularJS学习笔记(二) 表单验证案例(ng-repeat/filter)

这一节相对来说需要理解的东西不是太多,记住了那些api就行了. 还是一个案例(同样来自miaov),一个表单验证,先上代码,然后再对对应的内容进行解释. <!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>Title</title> </head>

angular学习笔记(二十四)-$http(2)-设置http请求头

1. angular默认的请求头: 其中,Accept 和 X-Requested-With是$http自带的默认配置 2. 修改默认请求头: (1) 全局修改(整个模块) 使用$httpProvider依赖 var myApp = angular.module('MyApp',[]); myApp.config(function($httpProvider){ console.log($httpProvider.defaults.headers.common) //修改/操作$httpProv

AngularJs学习笔记--directive

原版地址:http://code.angularjs.org/1.0.2/docs/guide/directive Directive是教HTML玩一些新把戏的途径.在DOM编译期间,directives匹配HTML并执行.这允许directive注册行为或者转换DOM结构. Angular自带一组内置的directive,对于建立Web App有很大帮助.继续扩展的话,可以在HTML定义领域特定语言(domain specific language ,DSL). 一.在HTML中引用direc

Caliburn.Micro学习笔记(二)----Actions

Caliburn.Micro学习笔记(二)----Actions 上一篇已经简单说了一下引导类和简单的控件绑定 我的上一个例子里的button自动匹配到ViewModel事件你一定感觉很好玩吧 今天说一下它的Actions,看一下Caliburn.Micro给我们提供了多强大的支持 我们还是从做例子开始 demo的源码下载在文章的最后 例子1.无参数方法调用 点击button把textBox输入的文本弹出来 如果textbox里没有文本button不可点,看一下效果图 看一下前台代码 <Stac

2. 蛤蟆Python脚本学习笔记二基本命令畅玩

2. 蛤蟆Python脚本学习笔记二基本命令畅玩 本篇名言:"成功源于发现细节,没有细节就没有机遇,留心细节意味着创造机遇.一件司空见惯的小事或许就可能是打开机遇宝库的钥匙!" 下班回家,咱先来看下一些常用的基本命令. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/48092873 1.  数字和表达式 看下图1一就能说明很多问题: 加法,整除,浮点除,取模,幂乘方等.是不是很直接也很粗暴. 关于上限,蛤蟆不太清楚

小猪的数据结构学习笔记(二)

小猪的数据结构学习笔记(二) 线性表中的顺序表 本节引言: 在上个章节中,我们对数据结构与算法的相关概念进行了了解,知道数据结构的 逻辑结构与物理结构的区别,算法的特性以及设计要求;还学了如何去衡量一个算法 的好坏,以及时间复杂度的计算!在本节中我们将接触第一个数据结构--线性表; 而线性表有两种表现形式,分别是顺序表和链表;学好这一章很重要,是学习后面的基石; 这一节我们会重点学习下顺序表,在这里给大家一个忠告,学编程切忌眼高手低,看懂不代表自己 写得出来,给出的实现代码,自己要理解思路,自己

JavaScript--基于对象的脚本语言学习笔记(二)

第二部分:DOM编程 1.文档象模型(DOM)提供了访问结构化文档的一种方式,很多语言自己的DOM解析器. DOM解析器就是完成结构化文档和DOM树之间的转换关系. DOM解析器解析结构化文档:将磁盘上的结构化文档转换成内存中的DOM树 从DOM树输出结构化文档:将内存中的DOM树转换成磁盘上的结构化文档 2.DOM模型扩展了HTML元素,为几乎所有的HTML元素都新增了innerHTML属性,该属性代表该元素的"内容",即返回的某个元素的开始标签.结束标签之间的字符串内容(不包含其它