Angular 1 笔记之五 路由 视图

AngularJS 通过将一个模板template,一个Controller和一个特定的URL联合起来,来达到功能路由。
每一个AngularJS Route都是由一个URL+一个template+一个Controller构成。

在传统的web应用程序中,我们为每个请求加载一个页面,多次加载一些重复的内容比如页面头部和底部内容。
但是当我们使用多个视图和路由时,就不能会有内容重复。
所有的子请求职更新特定页面的特定元素。

我们需要为每一个视图都创建一个单独的HTML文件。
然后告诉AngularJS那个route使用那个视图。

angular.module('myApp').config(function($routeProvider){
    $routeProvider.when('/view1',{
        controller:'controller1',
        templateUrl:'partials/view1.html',
    }).when('/view2',{
        controller:'controller2',
        templateUrl:'partials/view2.html',
    });
});


angular.module()有一个函数config(), 用于配置对module进行配置。
我们注入$routeProvider服务作为参数。

$routeParama 用于存储我们在URL定义的路由变量。
/view2/:firstname/:lastname
同时也会将URL的查询字符串以key/value的方式保存。

$location 内建服务对象,能够解析浏览器地址栏中的URL。

$location.path()用于加载一个新的路由。


使用指令 ng-template
用于定义内联模板。
<script type="text/ng-template" id="/view2.tpl">
    <p>
    From View2.
    <ul>
        <li>First name: {{firstname}}</li>
        <li>Last name: {{lastname}}</li>
    </ul>
    </p>
</script>

<div ng-view></div>


在Route配置对象中解析属性:
Route Config对象中有一个resolve属性,我们作为$routeProvider.when()函数的第二个参数传入。
它通常用于传入一个controller依赖。 
比如一个controller需要获取系统中所有用户,通常使用AJAX调用完成。
那么这个工作就可以由resolve来完成。

我们提供一个对象作为resolve 属性的值。该对象包含键值,可以作为controller依赖的名字。
换句话说,我们用这些作为参数声明controller的构造函数。
这里的键值可以是字符串也可以是函数。如果是字符串,AngularJS 会以它为名字查找相应的服务。
如果是函数,则使用该函数的返回值。

现在,函数的返回值可以是两种类型,第一种是简单值,比如string,array,object等。
这种情况下,resolve中的依赖直接携带他们的值。
第二种是一种特殊情况,大多数情况下我们从函数返回的值是一个延迟类型,promise
这就意味着返回值只是一个占位符,将在未来处理。

比如我们假设AJAX获取一个post对象,当获取过程中网络出现问题,依赖没能成功获取其真实的值。
也就是说我们的promise中获取了一个拒绝值。 另一方面,如果一切顺利,resolve中的所有依赖都获取了正确的值,
这时候我们说依赖被成功解析。
如果所有的依赖都被成功解析,$routeChangeSuccess 事件将会被广播。
如果有一个依赖没能被成功解析,$routeChangeError事件就将会被广播。
我们可以通过$rootScope.$on()来订阅这些事件。

就是说我们在定义route时可以通过为when函数的第二个参数对象添加resolve属性对象
在该对象中定义一些该路由对应的Controller的依赖,然后在Controller定义中使用这些依赖。
'use strict';
angular.module('myApp', [
    'myApp.controllers',
    'ngRoute'
]);
angular.module('myApp').config(function($routeProvider,$locationProvider) {
    $routeProvider.when('/view1', {
    controller: 'Controller1',
    templateUrl: '/partials/view1.html'
    }).when('/view2/:firstname/:lastname', {
        controller: 'Controller2',
        templateUrl: '/partials/view2.html',
        resolve: {
            names: function() {
                //typically you will use a service to retrieve values from the server here
                return ['Misko', 'Vojta', 'Brad']; //this is used as dependency value
            }
        }
    }).otherwise({
        redirectTo: '/view1'
    });
    $locationProvider.html5Mode(true);
});

上面我们在/view2 route中定义了一个依赖对象 作为resolve的值,该对象包含一个names 依赖项。
我们可以在定义其Controller时直接引用该依赖项:
'use strict';

angular.module('myApp.controllers', []).controller('Controller1',function($scope,$location){
    $scope.loadView2=function(){
        $location.path('/view2/'+$scope.firstname+'/'+$scope.lastname);
    }
}).controller('Controller2',function($scope,$routeParams,names){
    //names is now a dependency
    $scope.firstname=$routeParams.firstname;
    $scope.lastname=$routeParams.lastname;
    $scope.names=names;
});


关于$location 服务:
$location是AngularJS内建服务,用于显示当前浏览器URL(从window.location获得)然后通过定义好的API
暴露它们。它还会保持它自身跟URL同步。
我们在$location中进行的任何改变都会被传递给URL,同样的URL的任何变化也都会在$location服务中更新。

我们可以使用该服务来导航不同的路由,或者通过监控$location的变化来在应用程序中提高响应的行为。

$location的更新不会导致整个页面的刷新。它只会加载一个新的路由,如果要触发一个全页面的刷新
或者重定向用户到一个不同的站点或者URL,我们可以使用$window.locaiton.href 来完成。

$location服务的API:
提高了多个读取和设置器来操作URL的属性,比如对主机,协议,端口的读操作。
对path,search,hash的读写操作等。

$location 是AngularJS Scope生命周期可用的。在浏览器URL变化时,可以通过更新自己并调用$apply()。
当我们调用$locaiton.path('url')时,它并没有直接反映到URL上,而是在提交后的digest循环中才完成的。

path 名字通常是 / 开头,如果没有,$location.path()会自动添加。

search:提供key/value对,作为URL的查询参数。
除了使用$routeParams设置路由参数外,还可以通过search方法设置查询参数,它将以键值对的形式追加到 ?后面。
$location.search(); //get an object that has key/values as search parameters
$location.search({key1:value1,key2:value2}); //set the search parameter

路由中的事件:
$location 有关的事件
$locationChangeStart: 该事件在浏览器中URL变化之前由$rootScope 广播。
$locationChangeSuccess:该事件在浏览器中URL发生变化后广播,如果我们监听$locationChangeStart事件
的处理器调用了preventDefault,那么该事件将不会被触发。

$route 关联事件:
$routeChangeStart:在AngularJS开始改变路由时,被广播。在这个点位,$route服务开始解析所有的依赖,
通常包括获取视图模板并解析定义在resolve属性里的所有依赖。
同样使用$rootScope.$on()来订阅事件。

module的run()方法在所有的模块都成功加载后才被执行。
$routeChangeSuccess:是在$route服务成功解析了所有依赖后被广播。
ng-view指令会监听该事件来实例化关联的controller并渲染视图。

$rootChangeError: 如果$route服务无法解析依赖,该事件就会被广播。

所有的以上事件都是在$rootScope内被广播出去的。

ng-include 指令:
有时候,我们需要将HTML 模板划分为可重用的部分,这些部分可以被包含到主视图中。
ng-include 指令可以用于获取,编译并包括一个外部HTML 片段到我们的主页面。
比如我们的主页面可能包含,header,footer,sidebar等。我们可以将这些组件放到不同的HTML文件里。
然后将它们包含到主页面上。
<p>
    <ng-include src="'/partials/fragments/selected-user.html'"></ng-include>
    <ng-include src="'/partials/fragments/all-users.html'"/></ng-include>
</p>


我们还可以通过ng-include 创建一个新的区域scope并继承父scope。
这里的父Scope是指controller的Scope。

如果我们有一个scope的model,它指向一个模板,我们可以直接将该model的name指向src
如果我们想传递一个字符串给src,那必须将字符串包裹到单引号里面。

UI路由:
使用ngRoute有一个非常严重的限制,不能嵌套视图。因为只有一个ng-view
随着应用业务的复杂化,我们需要多视图时,比如应用程序的管理员页面,需要加载多个字视图,
到一个admin的Panel中。这时我们就需要借助第三方的UI Router来完成。

第 7 章 理解AngularJS 表单
表单作为一个CRUD应用程序基本的必要元素,AngularJS为其提供了很好的表单API。
将表单控件绑定到Scope的model定义,并且能够方便的校验表单的每个控件。

表单的处理与表单控件的校验是主要问题。
表单只是一个容器,它将关联的输入控件组合到一起。
ng-model指令用于保持输入控件的value跟scope内定义的model保持同步。


一个表单就是一个AngularJS指令。每个指令都有一个Controller一直对应。

每个AngularJS Form指令实例化一个FormController
该Controller负责追踪该Form的子控件和它们的状态。
如果我们想表单添加一个name属性,FormController实例就会被发布并放到该名称下。
类似的,一个ng-model指令实例也会有一个NgModelController,
如果我们为该指令添加一个name属性字段,那么该实例就会被发布到该作用域。

NgModelController暴露一个API来校验字段,格式或者解析值,追踪字段的状态。

ng-form指令在我们想使用嵌套表单时非常有用。
浏览器不允许我们使用嵌套表单,如果我们有一个表单想对其中某些元素进行分组时,
我们可以使用ng-form指令,但是它不能替代表单,只用于分组字段并检验。

ng-model-options="{updateOn: 'blur'}""

Directive 本质就是通过将事件监听者附加到某个元素或者转换某些DOM元素来让HTML真正具备交互性。

从jQuery的观点看Directive:我们在jQuery中如何为元素添加特定行为呢?
比如实现日历,首先我们创建标准的html输入元素
<input type="text" class="date-picker"/>
然后通过JavaScript代码修改其默认的行为
$(".date-picker").datePicker();

angular.module('myApp',[]).directive('helloworld',function(){
    return {
        restrict:'AEC',
        replace: true,
        template:'<h3>Hello,world!</h3>'
    };
});

replace指定生成的模板是否替代应用该指令所在的HTML元素。
模板文件路径如果以 / 开始,则被解析为该模板路径是相对于webapp的根目录的路径。
如果没有 / 开头,则是认为相对于主视图index.html的路径设置。

我们还可以在index.html中使用<base href="/"/>,这个时候模板文件会被解析为相对于app根目录的的路径。

Link函数:
因为我们使用的指令模板有可能很复杂,包含其它指令,表达式{{}}等。
如果该模板没有经过与之相对应的Scope的编译的话,这些指令和表达式是毫无意义的。
这就是为什么每个指令都需要有一个自己的Scope对象。
为了能够使用scope,我们使用link函数,该函数由指令的link属性指定。
在link函数内,我们可以设置scope对象的model,观察这些models的变化,为DOM元素添加
事件监听者。如果我们执行任何的DOM操作,那么这里就是我们理想的存放地方。

angular.module('myApp', []);
angular.module('myApp').controller('MainController',function($scope) {
    $scope.message = 'I love AngularJS';
});

angular.module('myApp').directive('helloworld',function(){
    return{
        restrict:'AEC',
        replace:true,
        template:'<p ng-click="clearMessage()">Hello, World!{{message}}</p>',
        link: function(scope,elem,attrs){
            scope.$watch('messae',function(value){
                console.log('Message Changed');
            });
            scope.clearMessage=function(){
                scope.message = '';
            }
            
            elem.bind('mouseover',function(){
                elem.css('cursor','pointer');
            });
        }
    }
});

<body ng-controller="MainController">
    <input type="text' ng-model="message" placeholder="Enter message" />
    <hello-world></hello-world>
</body>

这里的scope默认是父控件的controller对应的scope,比如该例中应该是MainController对应的scope
所以我们能够修改其内部定义的model。
当然,我们完全可以定义自己的scope。

elem变量是指我们指令应用到的元素,该元素已经由jQLite包裹。
这里jQLite是jQuery的一个子集,它支持基本的DOM操作。
如果我们需要使用jQuery的全部功能,我们只需要在AngularJS之前加载jQuery脚本。
只要在AngularJS之前加载jQuery,AngularJS就会用jQuery包裹elem元素然后传递给link函数。

attrs:它是一个map集包含了指令设置的HTML元素的所有属性和值对。
<hello-world some-attribute></hello-world>
我们可以在link函数里通过attrs.someAtrrtibute 来访问它。
即使你把指令作为某个元素的属性来使用,也可以访问到该元素的所有属性内容。


我们的指令在模板中使用了一个数据表达式,当用户输入字段内容是,表达式自动变化。
这是因为我们的指令的scope跟包裹指令的controller范围一致。

在link函数里,我们在scope上创建了一个监控器,来监控message model。

我们还创建了一个clearMessage()函数,来做message清除处理。

Compile函数:
跟link函数一起还有一个重要的函数,compile,该函数通过指令的compile属性指定。
该属性函数用于在link函数运行之前执行DOM转换操作。
注意compile函数无法访问scope对象,并且必须返回一个link函数。
如果定义中不存在Compile函数,我们可以直接配置link函数。

compile函数需要另个参数,tElement和attrs
tElement:该参数是指应用了指令的元素。前缀t指这是一个模板元素并且目前没有对应的scope可用。
attrs:定义在元素上的属性集合。

angular.module('testModule').directive('testDirective',function(){
    return{
        restrict:'AEC',
        replace:true,
        templateUrl:'',
        compile:function(tElem,attrs){
            //tElem 被jQLite/jQuery包裹
            return function(scope,elem,attrs){
                //linking function here
            };
        }
    };
});

大多数情况下,我们只直接使用link函数定义,因为大部分的指令只关心
注册监听者,观察者,更新DOM等这些在link函数里就可以完成了。

比如ng-repeat,它需要克隆和重复DOM元素多次,则需要在执行link之前通过compile完成。

指令的编译:
在Angular应用程序启动时,AngularJS使用$compile服务解析DOM文档。
从文档的标记中查找指令并跟注册过的指令进行匹配,一段所有的指令都被识别以后。
AngularJS就会执行compile函数。该函数返回一个link函数,该函数会被添加到link函数列表中等待执行。
以上这个过程被称为编译阶段。
如果指令需要被克隆多次,compile函数就用来干这个工作,而link函数则是每个克隆实例都要运行一次。
这就是为什么compile函数不接受一个scope的原因。

在编译阶段过后,就是链接阶段。在该阶段之前收集到的所有link函数列表会依次被执行。
该阶段模板会跟相应的scope一起被解析,转换为具备交互功能的DOM内容。

改变指令的Scope
默认情况下,一个指令会使用其父scope,但是很多时候,我们并不想这样。
如果我们将父scope暴露给指令,那么它可以随意修改父Scope中定义的内容。
在某些情况下,我们的指令可能想添加内部使用的属性和函数。

我们这时有两个选择:
使用一个子scope,该scope以父scope为原型建立,所以它继承了父scope的内容。
另外一种是使用独立的scope,跟父scope没有任何瓜葛。

这些scope的内容可以通过指令的scope属性来指定其类型。
angular.module('myApp').directive('helloWorld', function() {
    return {
        scope: true, // 使用继承自父Scope的子scope
        restrict: 'AE',
        replace: true,
        template: '<h3>Hello, World!</h3>'
    };
});

上例中使用了一个继承自父scope的子scope定义,这是在我们需要让父scope内容下沉到子scope
时,使用scope:true,这样我们可以使用父scope中定义的内容同时新增一些自己的内容。

有一些情形,我们不需要父scope中定义的所有内容,可能需要额外的内容,那么我们可以定义
独立的scope

angular.module('myApp').directive('helloworld',function(){
    return{
        scope:{},
        restrict:'ACE',
        replace:true,
        remplate:'<h3>Hello, World!</h3>
    };
});

独立的scope对于我们建立一个可重用的组件非常有用。
通过隔离scope我们可以保证我们定义的指令是自包含的,可以很容易的插入到HTML应用中。

这样可以保护父scope不被污染,因为在其中无法放父scope定义的属性和函数。

http://www.codeproject.com/Articles/1105334/High-Governance-of-No-Framework-Part

http://www.codeproject.com/Articles/1101082/AngularJS-ng-repeat-alternative

http://www.codeproject.com/Articles/375413/RaptorDB-The-Document-Store
http://blog.netgloo.com/2014/10/06/spring-boot-data-access-with-jpa-hibernate-and-mysql/

http://www.concretepage.com/
在独立scope和父scope之间建立绑定:

1、使用@ 在独立的scope与父scope之间进行单向绑定。

angular.module('myApp').directive('helloworld',function(){
    return{
        restrict:'AEC',
        scope:{
            message:'@messageAttr'
        },
        replace:true,
        template:'<p ng-click="clearMessage()">Hello, World!{{message}}</p>',
        link:function(scope,elem,attrs){
            //
        }
    };
});

<body ng-controller="MainController">
    <input type="text" ng-model="message" placeholder="Enter message" />
    <hello-world message-attr="{{message}}"></hello-world>
</body>

上例中我们在独立的scope中添加了一个属性message,并将其绑定到messageAttr属性上。
该属性对应于HTML中message-attr属性。

@是在独立scope定义的model和父scope属性之间建立一种单向绑定。
这里的单向是指我们只能给属性传递字符串。
当父scope的属性变化时,独立scope的model也跟着变化。
但是当独立scope的model发生变化时,却不能影响父scope的属性。

2、使用 = 建立双向绑定
跟@不同,它会将一个真正的scope model赋给属性而不仅仅是传递给它一个字符串。
这样我们不仅可以传递简单的字符串还可以传递复杂对象数组到独立scope。
由于是双向绑定,父scope属性的变化能够影响独立scope的属性变化,反之亦然。

scope: {
    message:'=messageAttr' // notice = instead of @
},
在模板中,我们不再使用{{}} 而是传入scope model
<hello-world message-attr="message"></hello-world>

3、使用 & 在父scope 执行函数
有时候我们需要从一个具有独立scope的指令中调用定义在父Scope的函数。
引用定义在外scope中的函数我们使用 & 

scope:{
    message:'=messageAttr',
    showMessage:'&showMessageAttr' // Bind with parent scope function
},

scope.$watch('message', function(value) {
    scope.showMessage(); // This will call the function defined by enclosing controller
});

<hello-world message-attr="message" show-message-attr="showMessage()"></hello-world>

在我们想向父scope定义的函数传入参数时,我们需要在HTML中列出这些参数

$scope.showMessage = function(arg){
    console.log('Message Changed with argurment ' + arg);
}

<hello-world message-attr="message" show-message-attr="showMessage(arg)"></hello-world>

在我们的指令定义中,我们需要为调用传入包含参数名和值的对象。
scope.$watch('message',function(value){
    scope.showMessage({arg:'sample argument'});
});

如果隔离scope属性和属性名相同,则可以省略属性名。
angular.module('myApp').directive('helloWorld', function() {
    return {
        restrict: 'AEC',
        scope: {
            message:'@' // No messageAttr
        },
        //Rest of the code
    }
});
对应的HTML:
<hello-world message="{{message}}"></hello-world>


$parent 是一个独立的scope
每个scope对象都包含一个特殊的属性$parent, 它指向父scope。
独立的scope也有一个$parent属性,它指向controller或者directive的scope。


父scope,子scope和独立scope之间的关系:
默认情况下,指令不会自己创建scope,而是直接采用应用指令所在父scope。
但是很多时候,让任何一个指令都能修改父scope 的内容是很危险的。

scope:false 是采用父scope,属于默认情形。如果我们的指令不对父scope的属性进行任何操作,
那么我们不需要创建一个新的scope,直接使用父scope就ok了。
scope:true 是采用创建子scope,此时子scope会继承父scope,从而能够访问父scope的所有内容,
同时又能够添加自己的定义。

scope:{} 是独立scope,类似一个沙箱,跟父scope没有直接关系。我们一般在创建一个自包含并
可重用的指令时,使用该类型的scope。该scope不继承任何scope。


Transclusion:嵌入
设置它可以让我们用指令包裹任意内容。
我们可以抽取并基于对应的scope编译它,最终放回到指令模板指定的位置。
transclude:true,一个新的嵌入scope就会被创建出来,该嵌套scope会以其父scope为原型创建。
如果我们想让指令有一个自己独立的scope来包含任意内容并基于父scope来执行它,那么我们需要
设置该条件。

angular.module('test').directive('outputText',function(){
    return{
        transclude:true,
        scope:{},
        template:'<div ng-transclude></div>'
    }
});

<div output-text>
    <p>Hello {{name}}</p>
</div>

注意这里的表达式{{name}}是定义在父scope中的而不是定义在指令的独立scope中。

transclude:'element' 和 transclude:true 之间的区别
有时候我们需要嵌入一个元素,指令应用到该元素而不仅仅是内容。
在这种情况下,我们设置transclude:'element',跟true不同,包含元素本身倒指令模板标记为ng-transclude
我们的link函数获取一个嵌入link函数预绑定到正确的指令scope。
这个link函数访问要嵌入的DOM元素的拷贝
我们可以执行一些任务,比如修改克隆,添加它到DOM等。

下面的例子重复DOM元素部分使用该技术在第二个实例修改背景颜色。

angular.module('myApp', []).directive('transcludeDirective',function() {
    return {
        transclude: 'element',
        scope: {},
        restrict: 'AE',
        replace: true,
        link: function(scope, elem, attrs, ctrl, transclude) {
            transclude(function(clone) { //'clone' is the clone of the directive element
                clone.css('background-color', 'yellow');
                elem.after(clone); //append the clone
            });
        },
        template: '<div ng-transclude></div>'
    }
});

使用该指令时
<p transclude-directive>Hello World!</p>


12

AngularJS的依赖注入
AngularJS通过Service Locator来进行依赖管理。
AngularJS查找匹配参数名称的注册服务然后自动将服务作为参数注入。

每个service都有一个关联的provider,$provider提供一个provider方法来注册它。
angular.module('myApp',[]).config(function($provide){
    $provide.provider('alertService',function(){
        this.$get = function(){
            return function(){
                alert('Service in action');
            }
        }
    });
});

我们可以将$provide 服务放到模块的config块中,我们就可以通过调用$provide.provider()方法
来注册新的provider。其它组件比如controller就可以被注入了
function simpleController(alertService){
    alertService();
}

当我们调用alertService时,其对应的provider的$get方法被调用,然后返回注入对象。
$provide除了提供provider()方法外,还提供service(),factory(),value(),constant()等来
注册不同类型的可注入类型。为了方便,这些方法也提供在module级别,我们可以直接通过module
访问。

另外一个秘密就是factory(),value(),constant()等方法隐式创建provider而不用我们键入所有provider内容。

上面例子我们通过provider创建alertService,现在我们看看如何使用factory做同样的事。

app.config(function($provider){
    $provide.factory('alertService',function(){
        return function(){
            alert('Service in Action');
        }
    });
});

angular.module('myApp').factory('alertService',function(){
    return function(){
        alert('Service in Action');
    }
});


$injector 服务:
真正负责实例化可注入类型并解析依赖项。
$provider服务注册可注入类型到$injector

$injector 使用$provider服务提供的代码实例化可注入类型。

function TestController($scope,$http,customService){
    //controller code goes here
}

$injector.instantiate(TestController);
在实例化该controller时$injector遍历其参数列表并调用$injector.get(serviceName)来获取
匹配的服务实例。在这个过程中,provider的$get()方法会被调用来获取我们的服务实例。
换句话说,$injector的get方法指导如何解析一个依赖。

$injector同时还提供了invoke()方法,需要一个函数参数并调用它来解析依赖。
$injector.invoke(function(customService,$http){    
    //some code here
});

这就出现了一个问题,如何来访问$injector呢?
答案很简单就是将它注入到我们的服务或者controller里。
$injector指导如何将自己注入,实际上,AngularJS在应用程序启动时就为我们的整个应用程序级
创建一个$injector。

angular.module('myApp').srevice('customService',function($injector){
    var $http=$injector.get('$http');
    var $rootScope = $injector.get('$rootScope');
});

我们还可以在module的config块中获取$injector.
angular.module('myApp').config(['$injector',function($injector){
    //use $injector here
}]);

为选定的模块获取$injector
var injector=angular.injector(['ng','customModule']);


动态注入依赖
$injector.get()通过服务名来获取依赖对象。
angular.module('myApp',[]).controller('SimpleController',['$injector',function($injector){
    $scope.getDependency = function(serviceName){
        var service = $injector.get(serviceName);
        //use service here
    }
    $scope.getDependency('$http');
}]);


Controllers,Filters,和Directives的注册:

controller: 有一个$controller服务或者叫$controllerProvider,它来负责创建我们的controller.
$controllerProvider.register()方法用于注册一个新的controller。
当我们定义angular.module().controller()注册一个controller时,实际是$controllerProvider.register()
在背后被调用。

filter:过滤器通过$filterProvider.register()方法来注册。
如果你想在其它组件中获取一个过滤器实例,可以通过调用$filter(filterName)来完成。
当然这里需要首先声明$filter服务。

directive:AngularJS有一个内建的服务$compiler,指令通过$compileProvider.directive()方法来注册。
通过$compile服务我们可以手动编译一个HTML字符串然后链接它到一个scope来插入绑定和添加元素到DOM

angular.module('myApp').directive('compileDirective',['$compile','$rootScope',function($compile, $rootScope) {
    return {
        restrict: 'A',
        link: function(scope, elem, attrs) {
            var html = '<div>Hello, World! {{message}}</div>';
            var element = $compile(angular.element(html))(scope);
            //get the element by compiling and linking it
            elem.after(element); // add the compiled element to the DOM
        }
    }
}]);

首先,$compile 服务需要传入一个DOM
angular.element()方法用于创建一个jQuery/jQLite包裹的元素。

内建的filter,
angular.module('myApp',[]).controller('FriendsController',function($scope,$filter){
    $scope.friends = [{
        name:'Sandeep',
        phone:'phone: '7432453412',
        country: 'IN'
        }, {
            name: 'John',
            phone: '8647323423',
            country: 'US'
        }, {
            name: 'Alex',
            phone: '5453562353',
            country: 'NZ'
        }, {
            name: 'Martin',
            phone: '2376454323',
            country: 'US'
        }, {
            name: 'Ian',
            phone: '8645432364',
            country: 'AU'
        }, {
            name: 'Rob',
            phone: '8967654567',
            country: 'UK'
    }];
    
    
<body ng-controller="FriendsController">
    <h3>Your Friends are:</h3>
    Filter: <input type="text" ng-model="filterText"/>
    <ul>
        <li ng-repeat="friend in friends | filter: filterText">
            {{friend.name}} ({{friend.phone}}, {{friend.country}})
        </li>
    </ul>
</body>


15 
部署问题
由于我们的源代码被分成了许多javascript文件。
加载这些文件会造成并行阻塞。
在同一个域中并行下载文件的请求数量也是有限的。
当浏览器遇见<script>标签式,它会停止渲染而开始执行脚本。
当然我们可以为<script>标签设置async属性,让其异步下载。

以上问题我们给出的方案是,连接所有的脚本文件成一个文件。
这样浏览器能够在一个单一的HTTP请求里将其下载。

仅仅连接文件是远远不够的,我们还要减小脚本文件大小。

我们同样也需要连接并压缩CSS文件。

所以最好将我们的源代码和部署代码分开放置。

转载于:https://my.oschina.net/u/924064/blog/903340

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值