Angularjs笔记

Angular

angular主要致力于减轻前端人员开发ajax应用程序的痛苦


MVC


MVC核心概念:把管理数据的代码(model)、应用逻辑代码(controller)、向用户展示数据的代码(view)清晰的分离开。
在angular应用中:视图就是DOM,控制器就是javascript类,模型数据则被存储在对象的属性中。

数据绑定


单向数据绑定


很多传统的模板系统数据绑定都是单向的,如下图:

它们将模板和数据合并起来加入到视图中去,如图表中所示。合并完成之后,从图中的流向可以看出,任何对数据模型或者相关内容的改变都不会自动反映到视图中去。而且用户对视图的任何改变也不会自动同步到数据模型中来。这意味着,开发者需要编写代码来保持视图与模板、模板与视图的同步,无疑增加了开发的工作量。

双向数据绑定


angularjs里的数据绑定模式为MVVM,即双向数据绑定,如下图:

双向数据绑定允许你把应用中的模型看成单一数据源。而视图始终是数据模型的一种展现形式。当模型改变时,视图就能反映这种改变,反之亦然。数据模型(model)与视图(view)组件的自动同步。

Controller


controller作用域问题


 <div ng-app="">

        <div ng-controller="firstController">
            <input type="text" value="" ng-model="name"/>

            <div ng-controller="secondController">
                <input type="text" value="" ng-model="name"/>
            </div>
        </div>
    </div>
var firstController = function($scope){

    $scope.name = '张三';
    console.log($scope);

}

var secondController = function($scope){

    console.log($scope);
}
ng-app=""(默认模块)的情况下,控制器函数为全局函数,嵌套在里面的控制器的作用域优先级高于外层的,如果secondController 作用域没有name属性,则会沿着作用域链向上查找。



ng-bind


<div ng-controller="firstController">
            <input type="text" value="" ng-model="name"/>
            <input type="text" value="" ng-model="age"/>
            <div ng-bind="name"></div>
            {{name}}
            <div ng-bind="age"></div>
            {{age}}
</div>
ng-bind主要用来解决当angular加载过慢时,angular来不及解析页面,页面会显示{{name}}等表达式

双向数据绑定原理($apply、$digest、$watch)


$watch


$watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你,我们可以在回调函数编写相应代码
var firstController = function($scope){

    $scope.name = '张三';
    $scope.data = {
        name :'李四',
    }
    // 监听一个model,初始化是触发一次,以后每当model改变时都会触发
    $scope.$watch('name',function(newValue,oldValue){
    	console.log("watch_name")
    });
    setInterval(function(){
    	$scope.name = "张三1";
    	$scope.$apply();
    },1000)

    $scope.$watch('data',function(){
        console.log("watch_data.name")
    },true)
    setInterval(function(){
        $scope.data.name = "李四1";
        $scope.$apply();
    },1000)
}

可以看到,一次是controller初始化的时候触发的,另一次是定时器改变了model的值,如果我们在定时器中不改变name的值
setInterval(function(){
        $scope.name = "张三";
        $scope.$apply();
},1000)
定时器虽然会触发name属性的监听器,但是不会调用回调函数,因为name属性的值没有改变

$digest()


$digest()是全局作用域$rootScope中的一个方法,用来进行脏检查。$digest循环开始后,它会触发每个watcher。这些watchers会检查scope中的当前model值是否和上一次计算得到的model值不同。如果不同,那么对应的回调函数会被执行。$digest循环一旦触发会执行两次。

$apply()


当我们手动调用$apply()后,$apply()会调用$rootScope.$digest()进行脏值检查。

$apply()和$apply(function(){})的区别是,当你传入一个function到$apply()中的时候,这个function会被包装到一个try…catch块中,所以一旦有异常发生,该异常会被$exceptionHandler service处理。
$apply: function(expr) {
    try {
        beginPhase('$apply');
        return this.$eval(expr);//解析函数字符串
    } catch (e) {
        $exceptionHandler(e);
    } finally {
        clearPhase();
        try {
            $rootScope.$digest();
        } catch (e) {
            $exceptionHandler(e);
            throw e;
        }
    }
}

angular双向数据绑定原理

angular并不存在定时脏检测。angular对常用的dom事件,xhr事件等做了封装, 在里面触发进入angular的digest流程。在digest流程里面, 会从rootscope开始遍历, 检查所有的watcher。

谈起angular的脏检查机制(dirty-checking), 常见的误解就是认为: ng是定时轮询去检查model是否变更。
其实,ng只有在指定事件触发后,才进入$digest cycle:

  • angular系统自带的DOM事件,譬如用户输入文本,点击按钮等。(ng-click)
  • XHR响应事件 ($http)
  • 浏览器Location变更事件 ($location)
  • Timer事件($timeout, $interval)
  • 执行$digest()或$apply()

angular模块


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <div ng-app="myApp">
        <div ng-controller="firstController">
            {{name+a}}<!--a是无效的,不能使用全局变量-->
        </div>
    </div>
<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
<script type="text/javascript" src="app/index.js"></script>
</body>
</html>
var myApp = angular.module('myApp',[]);
myApp.controller('firstController',function($scope){
    $scope.name = '张三';
});
function firstController($scope){
    $scope.name = '李四';
}
var a=5;
angular应用有一个默认的模块ng-app="",可以使用全局的函数作为控制器(但是不能使用全局变量),上面的输出结果为张三,如果我们指定了模块名称,则控制器会是myApp模块里的firstController,如果myApp模块里没有firstController,则是使用全局的firstController函数作为控制器。

使用模块的优点:可以将不同功能封装在不同的模块中,使用的时候直接依赖进来即可。

$provide


$provide用来自定义服务
var myApp = angular.module('myApp',[],function($provide){
    // 自定义服务
    $provide.provider('CustomService',function(){
        this.$get = function(){
            return {//也可以返回基本类型
                message : 'CustomService Message'
            }
        }
    });
    // 自定义工厂,相当于$provide.provider,只是少了调用$get方法的步骤
    $provide.factory('CustomFactory',function(){//myApp.factory()
        return [1,2,3,4,5,6,7];//也可以返回基本类型
    });
    // 自定义服务,相当于$provide.factory,不过只能返回对象
    $provide.service('CustomService2',function(){//myApp.service()
        return 'aaa';//无效返回,只可以返回对象
    })
});
myApp.controller('firstController',function($scope,CustomService,CustomFactory,CustomService2){
    $scope.name = '张三';
    console.log(CustomService);//Object {message: "CustomService Message"}
    console.log(CustomFactory);//[1, 2, 3, 4, 5, 6, 7]
    console.log(CustomService2);//Constructor {},
});
/*myApp.factory('CustomFactory',function(){
    return [1,2,3,4,5,6,7];
});
myApp.service('CustomService2',function(){
    return "aa";//无效返回,只可以返回对象
});*/
在控制器里自动注入的服务,参数顺序可以是任意的

多个controller里共享数据


多个控制器里共享数据有两种方法:
  • 1.使用作用域链
  • 2.使用自定义服务
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <div ng-app="myApp">
        <div ng-controller="firstController">
            first.data <input type="text" ng-model="data.name" />
            first.Data <input type="text" ng-model="Data.message" />
            <p>
                first-name:{{data.name}}
            </p>
            <p>
                first-message:{{Data.message}}
            </p>
        </div>
        <div ng-controller="secondController">
            <p>
                second-name:{{data.name}}
            </p>
            <p>
                second-message:{{Data.message}}
            </p>
        </div>
    </div>
<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
<script type="text/javascript" src="app/index.js"></script>
</body>
</html>
angular.module('myApp',[])

.factory('Data',function(){
    return {
        message : '共享的数据'
    };
})

.controller('firstController',function($scope,Data){
   $scope.data  = {
       name : '张三'
   };

   $scope.Data = Data;
})

.controller('secondController',function($scope,Data){
   $scope.data = $scope.$$prevSibling.data;//上一个控制器的作用域

   $scope.Data = Data;
});

过滤器


数组过滤器可以自定义函数
 {{ data.city | filter : checkName }}
 $scope.checkName = function(obj){
        if(obj.py.indexOf('h') === -1)
            return false;
        return true;
 }

自定义过滤器
<div ng-app="myApp">
    <div ng-controller="firstController">
        <ul>
            <li ng-repeat="user in data | filterCity">
                {{user.name}}
                {{user.age}}
                {{user.city}}
            </li>
        </ul>
    </div>
</div>
var myApp = angular.module('myApp', [], function ($filterProvider, $provide, $controllerProvider) {
    $provide.service('Data', function () {
        return [
            {
                name: '张三',
                age: '20',
                city: '上海'
            },
            {
                name: '李四',
                age: '30',
                city: '北京'
            }
        ];

    });
    //可以用$filterProvider注册过滤器
    $filterProvider.register('filterAge', function () {
        return function (obj) {
            var newObj = [];

            angular.forEach(obj, function (o) {
                if (o.age > 20) {
                    newObj.push(o);
                }
            });
            return newObj;
        }
    });
    $controllerProvider.register('firstController', function ($scope, Data) {
        $scope.data = Data;
    });
})
//用模块方法注册过滤器
.filter('filterCity',function(){
    return function(obj){//obj为要过滤的对象或者基本类型
        var temp = arguments
        debugger;
        console.log(obj)
        var newObj = [];

        angular.forEach(obj, function (o) {
            if (o.city === '上海') {
                newObj.push(o);
            }
        });
        return newObj;
    }
})

显示和隐藏的依赖注入


var myApp = angular.module('myApp', [], ['$filterProvider', '$provide', '$controllerProvider', function (a, b, c) {
    console.log(a, b, c);
}])
.factory('CustomService', ['$window', function (a) {
    console.log(a);
}])
// 隐示的依赖注入
.controller('firstController', function ($scope, CustomService) {
    console.log(CustomService);
})

// 显示的依赖注入
.controller('secondController', ['$scope', '$filter', function (a, b) {
    console.log(b('json')([1, 2, 3, 4, 5]));
}]);

function otherController(a) {
    console.log(a);
}
otherController.$inject = ['$scope'];

指令


渲染指令


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
<div ng-app="myApp">
    <div>
        <p>{{1+1}}</p>
        <p ng-bind="1+1"></p>
        <!-- xml校验写法 -->
        <p ng:bind="1+1"></p>
        <!-- html5校验写法 -->
        <p data-ng-bind="1+1"></p>
        <!-- xhtml校验写法 -->
        <p x-ng-bind="1+1"></p>
        <p ng-bind-template="{{1+1}}"></p>
        <!-- $scope.cityArr = ['上海','北京','杭州'] -->
        <ul ng-class="{red:status}" ng-init="cityArr = ['上海','北京','杭州','广州']">
            <li ng-class-even="'偶数'" ng-class-odd="'奇数'" ng-repeat="city in cityArr" >
            <span>
                index:{{$index}}
            </span>
            <span>
                first:{{$first}}
            </span>
            <span>
                middle:{{$middle}}
            </span>
            <span>
                last :{{$last}}
            </span>
            <span>
                {{city}}
            </span>
            </li>
        </ul>
        <div ng-include="'other.html'">
        </div>
        <div ng-include src="'other.html'">
        </div>
    </div>
</div>
<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
</body>
</html>

事件指令


<div ng-app="myApp">
    <div ng-controller="firstController">
        <!-- 注意:这里的函数必须执行 -->
        <button ng-click="changeStatus($event)">切换状态</button>
        {{status}}
    </div>
</div>
var myApp = angular.module('myApp', [])

.controller('firstController', function ($scope) {
    $scope.status = false;
    $scope.changeStatus = function (event) {
        // 通过element转换成 jquery对象
        angular.element(event.target).html('切换状态为:' + $scope.status);

        $scope.status = !$scope.status;

    }
})

节点指令


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        .red{
            color:red;
        }
        .blue{
            color:blue;
        }
    </style>
    <script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
    <script type="text/javascript" src="app/index.js"></script>
</head>
<body>
<div ng-app="myApp">
    <div ng-controller="firstController">
        <div ng-style="{color:'red',fontSize:'40px'}">测试ng-style1</div>
        <div ng-style="defaultStyle">测试ng-style2</div>
        <div ng-class="{red:true}">测试ng-class1</div>
        <div ng-init="status=true"></div>
        <div ng-class="{red:status}">测试ng-class2</div>
        <ul  ng-init="cityArr = ['上海','北京','杭州','广州']">
            <li ng-class-even="'red'" ng-class-odd="'blue'" ng-repeat="city in cityArr" >
                {{city}}
            </li>
        </ul>
        <div ng-show="false">
            测试ng-show
        </div>
        <div ng-if="false">
            测试ng-if
        </div>
        <!-- 普通src属性里的表达式会延迟解决,会先加载{{src}}字符串 ,解析后再加载正确图片-->
        <img src="{{src}}"/>
        <img ng-src="{{src}}"/>
        <a ng-href="{{src}}">图片链接</a>
        <div ng-init="myVar='google'"></div>
        <!-- ng-switch-when里的表达式字符串不需要加引号,否则出错 -->
        <div ng-switch="myVar">
              <div ng-switch-when="google">
                 <h1>Google</h1>
              </div>
              <div ng-switch-when="taobao">
                 <h1>淘宝</h1>
              </div>
              <div ng-switch-default>
                 <h1>切换</h1>
              </div>
        </div>
        <div ng-init="myVar1=1"></div>
        <div ng-switch="myVar1">
              <div ng-switch-when="1">
                 <h1>1</h1>
              </div>
              <div ng-switch-when="2">
                 <h1>2</h1>
              </div>
        </div>
    </div>
</div>

</body>
</html>
var myApp = angular.module('myApp', [])

.controller('firstController', function ($scope) {
    $scope.defaultStyle = {
        color:'red',
        fontSize:"40px"
    };

    $scope.src = 'http://avatar.csdn.net/C/C/C/3_a409051987.jpg';
})
ng-if和ng-show的区别:ngIf 是完全不出现在 html 代码里, ngShow 是代码里有,但通过 CSS 隐藏了。

自定义指令


restrict、template、replace属性


<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
    <script type="text/javascript" src="app/index.js"></script>
</head>
<body>
<div ng-app="myApp">
   <directive-tag></directive-tag>
   <div directive-tag></div>
   <div class="directive-tag"></div>
   <!-- directive:directive-tag -->
</div>
</body>
</html>
var myApp = angular.module('myApp', [], ['$compileProvider',function ($compileProvider) {
    $compileProvider.directive("directiveTag", function() {
	    return {
	        restrict : "EACM",
	        template : "<h1>自定义指令!</h1>",
	        replace : true,//设置true以后,会把指令标签删除
	    };
	})
}])
//.directive('')

restrict 值可以是以下几种:
  • E 作为元素名使用
  • A 作为属性使用
  • C 作为类名使用
  • M 作为注释使用
设置为M是在页面是没有效果,也不会替换,但是会运行compile方法
设置replace为true和false的区别:




templateUrl属性


<div ng-app="myApp">
    <script type="text/ng-template" id="customTags2">
        <div>
            hello {{name}}
        </div>
    </script>
    <div ng-controller="firstController">
        <custom-tags></custom-tags>
        <custom-tags2></custom-tags2>
    </div>
</div>
var myApp = angular.module('myApp', [])

.directive('customTags', function () {
    return {
        restrict: 'ECAM',
        templateUrl: 'tmp/other.html',
        replace: true
    }
})

.directive('customTags2', function () {
    return {
        restrict: 'ECAM',
        templateUrl: 'customTags2',
        replace: true
    }
})

.controller('firstController', ['$scope', function ($scope) {
    $scope.name = '张三';
}]);
注意:tempate或者templateUrl里面的内容必须用一个标签包裹起来,不能是''<div>1</div><div>2</div>"或者"123"这种形式

tempateUrl里面可以是url或者是script type="text/ng-template"的id

transclude、priority、terminal属性

  • transclude用来保存原标签里原有的内容。
  • priority用来设置指令在模板中的执行顺序,顺序是相对于该元素上其他执行而言,指令默认的priority为0,一般不需要手动设置priority,像ng-repeat默认的priority为1000。
  • terminal用来设置是否以当前指令的权重为结束界限。如果设置为true,则节点权重小于当前指令的其他指令不会被执行。相同权重的会执行。
<div ng-app="myApp">
    <div ng-controller="firstController">
        <custom-tags>原始数据</custom-tags>
        <div custom-tags2 custom-tags3>
        </div>
    </div>
</div>
var myApp = angular.module('myApp', [])

.directive('customTags', function () {
    return {
        restrict: 'ECAM',
        template:'<div>新数据 <span ng-transclude></span></div>',
        replace: true,
        transclude:true
    }
})

.directive('customTags2', function () {
    return {
        restrict: 'ECAM',
        template:'<div>2</div>',
        replace: true,
        priority:-1
    }
})

.directive('customTags3', function () {
    return {
        restrict: 'ECAM',
        template:'<div>3</div>',
        replace: true,
        priority: 0,
        // 小于0的directive 都不会执行,否则还会继续解析customTags2里的template
        terminal:true
    }
})

.controller('firstController', ['$scope', function ($scope) {
    $scope.name = '张三';
}]);

compile、link属性


Angular指令编译三阶段:
  1. 将html转换成dom,所有自定义的html标签必须符合html的格式
  2. 搜索匹配directive,按照priority排序,如过子元素,则先执行父元素的指令,并执行directive上的compile方法
  3. 执行directive上的link方法,进行scope绑定及事件绑定
Compile 函数:

使用compile函数可在ng创建原始dom实例以及创建scope实例之前以改变原始的dom(template element)。

可以应用于当需要生成多个element实例,只有一个template element的情况,ng-repeat就是一个最好的例子,它就在是compile函数阶段改变原始的dom生成多个原始dom节点,然后每个又生成element实例.因为compile只会运行一次,所以当你需要生成多个element实例的时候是可以提高性能的。template element以及相关的属性是做为参数传递给compile函数的,不过这时候scope是不能用的。

preLink:

pre-link函数,它能够保证在执行所有子指令的pre-link和post-link函数之前运行一些别的代码。pre-link函数可以在angular执行完compile函数之后,所有子指令的post-link函数将要执行之前运行一些业务代码。scope对象以及element实例将会做为参数传递给pre-link函数。

postLink:

post-link函数,它能够保证在执行所有子指令的pre-link和post-link函数之后运行一些别的代码,它和pre-link的执行顺序相反,被认为是最安全以及默认的编写业务逻辑代码的原因。scope对象以及element实例将会做为参数传递给post-link函数。

link函数负责在模型和视图之间进行同台关联,对于每个指令的每个实例,link函数都会执行一次。可以用来给元素进行事件的注册

<div ng-controller="firstController">
        <div ng-repeat="user in users" custom-tags="" custom-tags2>

        </div>
</div>
var myApp = angular.module('myApp', [])
    .directive('customTags',function(){
        return {
            restrict : 'ECAM',
            template : '<div>{{user.name}}</div>',
            replace : true,
            //compile函数只运行一次
            compile:function(tElement,tAttrs,transclude){
                // 编译阶段,这个阶段是没有scope作用域的
                console.log('customTags compile 编译阶段...');
                tElement.append(angular.element('<div>点击次数:{{user.count}}</div>'));
                return {
                    // 表示在编译阶段之后,指令连接到子元素之前运行
                    pre:function preLink(scope,iElement,iAttrs,controller){
                        console.log('customTags preLink..');
                        //在link里改变可以改变dom结构,但是不会再解析里面的表达式
                        iElement.append(angular.element('<div>{{user.age}}</div>'));
                    },
                    // 表示在所有子元素指令都连接之后才运行
                    post:function postLink(scope,iElement,iAttrs,controller){
                        console.log('customTags all child directive link..');
                        iElement.on('click',function(){
                            scope.$apply(function(){
                                scope.user.count++;
                            });
                        })
                    }
                }
                // 可以直接返回 postLink
                // return postLink function(){
                    // console.log('compile return fun');
                //}
            },
            // 此link表示的就是 postLink,如果compile有返回函数,则不会执行这个link
            link:function(){
                console.log("执行link")
            }
        }
    })
    //这里template为空,同时定义customTags和customTags2不会报错
    .directive('customTags2',function(){
        return {
            restrict : 'ECAM',
            replace : true,
            compile:function(){
                // 编译阶段...
                console.log('customTags2 compile 编译阶段...');
                return {
                    // 表示在编译阶段之后,指令连接到子元素之前运行
                    pre:function preLink(){
                        console.log('customTags2 preLink..')
                    },
                    // 表示在所有子元素指令都连接之后才运行
                    post:function postLink(){
                        console.log('customTags2 all child directive link..')
                    }
                }

            }
        }
    })
    .directive('customTags3',function(){
       // return postLink;
       return function(){
       }
    })
    .controller('firstController', ['$scope', function ($scope) {
        console.log("firstController控制器初始化");
        $scope.users = [
            {
                count:0,
                name:'张三',
                age:26
            },
            {
                count:0,
                name:'李四',
                age:18
            },
        ];
    }]);

controller、controllerAs、require属性


<div ng-app="myApp">

    <div ng-controller="firstController">
        <div book-list>
        </div>
    </div>
</div>
var globalScope = null;
angular.module('myApp', [])

    .directive('bookList', function () {
        return {
            restrict: 'ECAM',
            controller: function ($scope) {//必须是$scope,是注入的
                console.log("bookList:"+(globalScope == $scope));//true
                this.books = [
                    {
                        name: 'php'
                    },
                    {
                        name: 'javascript'
                    },
                    {
                        name: 'java'
                    }
                ];
                var that = this;
                this.addBook = function(){

                    $scope.$apply(function(){
                        that.books.push({
                            name:'Angularjs'
                        })
                    });
                }
            },
            //将会在scope一个属性为bookListController的对象,存储了该controller属性的数据
            controllerAs:'bookListController',
            template: '<div><ul><li ng-repeat="book in bookListController.books">{{book.name}}</li></ul><book-add test-tag></book-add></div>',
            replace:true,
            link:function(scope,iElement,iAttrs,controller){
               
            }
        }

    })
     .directive('testTag',function(){
         return {
            restrict:'ECAM',
            controller:function(){
                this.test=function(){}
            },
        }
    })
    .directive('bookAdd',function(){
        return {
            restrict:'ECAM',
            //自己没定义controller属性,去依赖别的controller属性,也可以去查找该元素的其他指令,
            //此时就不需要用^号了,例如testTag
            require:'^bookList',
            template:'<button type="button">添加</button>',
            replace:true,
            controller:function(){
                this.addBook = function(){
                    alert("hehe")
                }
            },
            //将会在$scope里生成属性为bookAddController的对象,指向该指令的controller属性
            controllerAs:"bookAddController",
            link:function(scope,iElement,iAttrs,controller){
                //定义了require属性,这里的控制器是require过来的控制器,会覆盖自己定义的控制器
                console.log("bookadd:"+(globalScope == scope));//true
                //iElement.on('click',controller.addBook);
                debugger;//观察scope,请看下图
            }
        }
    })
    .controller('firstController', ['$scope', function ($scope) {
        $scope.name = "lisong"
        globalScope = $scope;
    }]);






从上面的代码可知:
  • 默认情况下,控制器下的所有自定义指令都只有一个相同的作用域,那就是控制器的$scope
  • 给自定义指令设置controllerAs属性,将会在$scope里生成一个对象,该对象执行了该指令的controller属性。
  • 如果指定了require属性,则link的最后一个参数会指向其他指令的controller属性,而覆盖该指令定义的controller属性。
require的参数:
  • directiveName:通过驼峰命名指定了控制器应该带有带有那一天指令,默认会从同一个元素上查找指令
  • ^directiveName:在父级查找指令
  • ?directiveName:表示指令是可选的,如果找不到,不需要抛出异常

scope属性


<div ng-controller="firstController">
    {{
        books
    }}
    <div book-list books="books" parent-books="books" parent-title="{{title}}">
    </div>
</div>
angular.module('myApp', [])
    .directive('bookList', function () {
        return {
            restrict: 'ECAM',
            controller: function ($scope) {
                // &books
                // $scope.books = $scope.a();
                // =books;
                // $scope.books = $scope.b;
                // $scope.b.push({name:'nodejs'});
                console.log($scope.c);
            },
            // 创建一个有继承链的独立作用域
            // scope:true,

            // 当为对象的时候也会创建一个独立的作用域
            scope:{
                // 将父元素books封装成一个a函数
                // a:'&books'
                // 双向绑定 b = parentBooks属性对应的父作用域的表达式
                // b:'=parentBooks'
                // 使用简单数据类型的方法
                c:'@parentTitle'
            },
            controllerAs:'bookListController',
            template: '<div><ul><li ng-repeat="book in books">{{book.name}}</li></ul></div>',
            replace:true

        }

    })
    .controller('firstController', ['$scope', function ($scope) {
        console.log($scope);
        $scope.books = [
            {
                name: 'php'
            },
            {
                name: 'javascript'
            },
            {
                name: 'java'
            }
        ];

        $scope.title = '张三';
    }]);

模块里的constant、value、run方法


angular.module('myApp',[],['$provide','$controllerProvider',function($provide,$controllerProvider){
    console.log('config1');
    // $provide.factory
    // $provide.service
    // $provide.constant
    // $provide.value;
    $controllerProvider.register("secondController",['APIKEY','vension',function(APIKEY,vension){
        console.log(APIKEY);
        console.log(vension);
        console.log('controller2');
    }]);
}])

.config(function(APIKEY){
    console.log(APIKEY);
    console.log('config2');
})

// 在config之后controller等其他服务之前。。
.run(function(){
    console.log('run');
})
// 它可以注入任何方法
.constant('APIKEY','xxxx')

// 只能注入controller...service factory
.value('vension','1.0.0')

.controller('firstController',['APIKEY','vension',function(APIKEY,vension){
    console.log(APIKEY);
    console.log(vension);
    console.log('controller1');
}]);


表达验证


<form name="myForm" action="kittencup.php"  class="container form-horizontal">
    <div class="form-group" ng-class="{'has-error':myForm.username.$dirty && myForm.username.$invalid}">
        <label class="col-sm-2 control-label">用户名</label>
        <div class="col-sm-10">
            <input type="text" autocomplete="off" name="username" ng-pattern="/^[a-zA-Z]{1}/" ng-required="true" ng-minlength="5" ng-maxlength="10" ng-model="username" class="form-control" placeholder="用户名">
            <div ng-show="myForm.username.$dirty && myForm.username.$error.maxlength" class="alert alert-danger help-block">
                用户名长度不能超过10位
            </div>
            <div ng-show="myForm.username.$dirty && myForm.username.$error.minlength" class="alert alert-danger help-block">
                用户名长度不能小于5位
            </div>
            <div ng-show="myForm.username.$dirty && myForm.username.$error.pattern" class="alert alert-danger help-block">
                用户名必须已英文字母开始
            </div>
            <div>用户名:{{username}}</div>
        </div>
    </div>

    <div class="form-group">
       <div class="col-sm-offset-2 col-sm-10">
           <button type="submit" class="btn btn-default" ng-disabled="myForm.$invalid || data.hobbies === undefined || data.hobbies.length === 0">注册</button>
           <button type="reset" class="btn btn-default" ng-click="reset()">重置</button>
       </div>

    </div>
</form>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值