JavaScript日记——Angularjs入门指南

本系列博客采用的Angularjs1.3进行开发

要入门Angularjs主要掌握以下概念

1.数据绑定(MVC)
2.scope
3.模块(module)
4.Directive
5.路由
6.依赖注入

数据绑定

首先是HelloWorld的教程

<!doctype html>
<!-- ng-app声明以下部分使用angularjs -->
<html ng-app>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <!-- 定义model -->
        <input type="text" name="msg" ng-model="name">
        <!-- 绑定model内容 -->
        <span ng-bind='name'></span>
        <!-- 因为加载js需要时间,下面这种方式可能会显示出花括号 -->
        <!-- <span >{{name}}</span> -->
    </body>
    <script src="js/angular-1.3.0.js"></script>
</html>

当我们改变input的内容时,model的值也会改变

下面介绍一下数据绑定如何运用在mvc设计模式中

<!doctype html>
<html ng-app>
<head>
    <meta charset="utf-8">
</head>
<body>
    <!-- 使用Controller作为中介 -->
    <div ng-controller="HelloAngular">
        <p><span ng-bind="greeting.text"></span>,Angular</p>
    </div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script >
    // 定义Controller,名字要和所绑定的ng-controller一样
    function HelloAngular($scope) {
        // scope代表作用域,每个controller都有自己的scope,接下来会详细介绍
        $scope.greeting = {
            text: 'Hello'
        };
    }
</script>
</html>

scope

scope是一个POJO,可以叫做作用域,可以继承父作用域的属性和方法,就是说当controller嵌套时,可以使用父controller里的scope的属性和方法
ng-app定义了一个angular模块, 每个模块只有一个$rootScope,只有一个$injector,但可以有多个$scope 。scope有点类似React的store,还有scope中也可以存放方法。

<!doctype html>
<html ng-app>
<head>
    <meta charset="utf-8">
</head>
<body>
    <div >
        <!-- 分别绑定不同的Controller -->
        <div ng-controller="GreetCtrl">
            <!-- 这个name属于GreetCtrl的scope -->
            Hello {{name}}!
        </div>
        <div ng-controller="ListCtrl">
            <ol>
                <li ng-repeat="name in names">
                    <!-- name是names中的迭代的对象 ,names属于ListCtrl的scope-->
                    <!-- department是rootscope的model,可以共用 -->
                    {{name}} from {{department}}
                </li>
            </ol>
        </div>
    </div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script >
    function GreetCtrl($scope, $rootScope) {
        $scope.name = 'World';
        // rootscope可以共用
        $rootScope.department = 'Angular';
    }

    function ListCtrl($scope) {
        $scope.names = ['Igor', 'Misko', 'Vojta'];
    }
</script>
</html>

模块化

通常我们为了避免全局变量污染,我们会引入module这个概念,有点类似命名空间
我们把上面MVC的例子改成模块化

<!doctype html>
<html ng-app="HelloAngular">
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <div ng-controller="helloAngular">
            <p>{{greeting.text}},Angular</p>
        </div>
    </body>
    <script src="js/angular-1.3.0.js"></script>
    <script type="text/javascript">
            // 首先为ng-app定义一个module,[]中填写依赖项
            var myModule = angular.module("HelloAngular", []);
            // 定义module所需的controller,引入scope
            myModule.controller("helloAngular", ['$scope',
                function HelloAngular($scope) {
                    $scope.greeting = {
                        text: 'Hello'
                    };
                }
            ]);
    </script>
</html>

Directive

我们可以使用Directive来匹配不同的dom,来显示不同模板,也可以用过这种方式实现view的复用
主要有四种匹配模式
A——匹配属性中含有指定值
C——class中含有指定值
M——一般标签,标签上有注释directive:指定值
E——匹配标签为指定值

<!doctype html>
<html ng-app="MyModule">
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <!-- 自定义hello标签 -->
        <!-- 匹配模式为E -->
        <hello></hello>
        <!-- 匹配模式为A -->
        <div hello></div>
        <!-- 匹配模式为C -->
        <div class="hello"></div>
        <!-- 匹配模式为M -->
        <!-- directive:hello -->
        <div></div>

    </body>
    <script src="js/angular-1.3.0.js"></script>
    <script >
        // 模块化
        var myModule = angular.module("MyModule", []);
        // 匹配hello
        myModule.directive("hello", function() {
            return {
                restrict: 'AEMC',//使用4种匹配模式
                template: '<div>Hi everyone!</div>',
                replace: true//完全代替标签里的内容
                //transculde表示互相嵌套
                // transclude:true,
                //<div ng-transclude></div>为原标签里的内容
                // template: '<div>Hi everyone!<div ng-transclude></div></div>',
            }
        });
    </script>
</html>

Directive除了可以代替指定标签的内容,还可以实现方法或者属性的操作

<!doctype html>
<html ng-app="MyModule">
<head>
    <meta charset="utf-8">
</head>
<body>
    <div ng-controller="MyCtrl1">
        <!-- 属性放不同的方法名 -->
        <loader howToLoad="loadData1()">LoadData1</loader>
    </div>
    <div ng-controller="MyCtrl2">
        <loader howToLoad="loadData2()">LoadData2</loader>
    </div>
    <script src="js/angular-1.3.0.js"></script>
    <script >
            // 模块化
            var myModule = angular.module("MyModule", []);
            myModule.controller('MyCtrl1',['$scope',function($scope){
                $scope.loadData1=function(){
                    console.log("loading1");
                }
            }]);
            myModule.controller("MyCtrl2",['$scope',function($scope){
                $scope.loadData2=function(){
                    console.log("loading2");
                }
            }]);
            // 匹配superman
            myModule.directive("loader", function() {
                return {
                    restrict:"AE",
                    // 三个参数分别是作用域,dom对象,属性
                    link:function(scope,elemenet,attrs){
                        //绑定标签方法,鼠标在标签上方时触发
                        elemenet.bind('mouseenter',function(){
                            // 下面都两种可以执行controller里的方法,若没有方法则报错
                            // scope.loadData1();
                            // scope.$apply("loadData1()");
                            
                            //执行相应属性的方法,属性名要全部小写
                            scope.$apply(attrs.howtoload);
                        });
                    }
            }
        });
        </script>
    </body>
</html>

以下例子实现指令的依赖(继承)

<!doctype html>
<html ng-app="MyModule">
<head>
    <meta charset="utf-8">
</head>
<body>
    <div class="row">
        <div class="col-md-3">
            <superman strength>动感超人——力量</superman>
        </div>
    </div>
    <div class="row">
        <div class="col-md-3">
            <superman strength speed>动感超人——力量+敏捷</superman>
        </div>
    </div>
    <div class="row">
        <div class="col-md-3">
            <superman strength speed light>动感超人——力量+敏捷+发光</superman>
        </div>
    </div>
    <link rel="stylesheet" type="text/css" href="css/bootstrap-3.0.0/css/bootstrap.css">
    <script src="js/angular-1.3.0.js"></script>
    <script >
            // 模块化
            var myModule = angular.module("MyModule", []);
            // 匹配superman
            myModule.directive("superman", function() {
                return {
                    scope:{},
                    //使用A和E模式
                    restrict:'AE',
                //暴露方法给指令调用
                controller:function($scope){
                    $scope.abilities=[];
                    this.addStrength=function(){
                        $scope.abilities.push("strength");
                    };
                    this.addSpeed=function(){
                        $scope.abilities.push("speed");
                    };
                    this.addLight=function(){
                        $scope.abilities.push("light");
                    };
                },
                link:function(scope,elemenet,attrs){
                    //修改元素class
                    elemenet.addClass('btn btn-primary');
                    //绑定标签方法,鼠标在标签上方时触发
                    elemenet.bind('mouseenter',function(){
                        console.log(scope.abilities);
                    });
                }
            }
        });
            myModule.directive('strength',function(){
                return {
                //依赖superman指令
                require:'^superman',
                //supermanCtrl是superman指令里的controller,需要把它注入到link中
                link:function(scope,elemenet,attrs,supermanCtrl){
                    supermanCtrl.addStrength();
                }
            }
        });
            myModule.directive('speed',function(){
                return {
                    require:'^superman',
                    link:function(scope,elemenet,attrs,supermanCtrl){
                        supermanCtrl.addSpeed();
                    }
                }
            });
            myModule.directive('light',function(){
                return {
                    require:'^superman',
                    link:function(scope,elemenet,attrs,supermanCtrl){
                        supermanCtrl.addLight();
                    }
                }
            });
        </script>
    </body>
</html>

如果想每一处都使用独立的scope,则要加上scope:{},不加则默认使用同一个scope,互相影响

<!doctype html>
<html ng-app="MyModule">
<head>
    <meta charset="utf-8">
</head>
<body>
    <hello></hello>
    <hello></hello>
    <hello></hello>
    <hello></hello>
    <script src="js/angular-1.3.0.js"></script>
    <script >
            // 模块化
            var myModule = angular.module("MyModule", []);
            // 匹配superman
            myModule.directive("hello", function() {
                return {
                    scope:{},//使用独立的scope,每一处匹配的标签的scope都是独立的,不互相影响
                    restrict:"AE",
                    template:'<div><input type="text" ng-model="userName"/>{{userName}}</div>'
                }
            });
    </script>
</body>
</html>

scope的绑定有三种方式:@,=,&

<!doctype html>
<html ng-app="MyModule">
<head>
    <meta charset="utf-8">
</head>
<body>
    <div ng-controller="MyCtrl">
        Ctrl:
        <input type="text" ng-model="ctrlFlavor">
        <br>
        Directive:
        <drink flavor="ctrlFlavor"></drink>
    </div>
    <script src="js/angular-1.3.0.js"></script>
    <script >
            // 模块化
            var myModule = angular.module("MyModule", []);
            myModule.controller('MyCtrl',['$scope',function($scope){
                $scope.ctrlFlavor="百威";
            }])
            // 匹配drink
            myModule.directive("drink", function() {
                return {
                    restrict:"AE",
                    template:'<input type="text" ng-model="flavor"/>{{flavor}}',
                    scope:{
                        flavor:'='//双向绑定model,绑定该属性值的model,改变任一个model都会互相影响
                    }
                    // scope:{
                    //  flavor:'@'//将原来该名字属性的字符串传递下来 ,和下面表达相等
                    // }
                    // link:function(scope,element,attrs){
                    //  scope.flavor=attrs.flavor;
                    // }
                }
            });
    </script>
</body>
</html>

如果要传递方法则要使用&

<!doctype html>
<html ng-app="MyModule">
<head>
    <meta charset="utf-8">
</head>
<body>
    <div ng-controller="MyCtrl">
        <greeting greet="sayHello(name)"></greeting>
        <greeting greet="sayHello(name)"></greeting>
        <greeting greet="sayHello(name)"></greeting>
    </div>
    <script src="js/angular-1.3.0.js"></script>
    <script >
            // 模块化
            var myModule = angular.module("MyModule", []);
            myModule.controller('MyCtrl',['$scope',function($scope){
                $scope.sayHello=function(name){
                    alert("hello"+name);
                }
            }])
            // 匹配superman
            myModule.directive("greeting", function() {
                return {
                    restrict:"AE",
                    template:'<input type="text" ng-model="userName"/><br/><button ng-click="greet({name:userName})"> greeting</button><br>',
                    scope:{
                        greet:'&'//将原来该名字属性的方法传递下来
                    }
                }
            });
    </script>
</body>
</html>

路由

<html>
    <head>
      <meta charset="utf-8">
    </head>
    <body ng-app='routingDemoApp'>
        <h2>AngularJS 路由应用</h2>
        <ul>
            <!-- 设置不同url -->
            <li><a href="#/">首页</a></li>
            <li><a href="#/computers">电脑</a></li>
            <li><a href="#/printers">打印机</a></li>
            <li><a href="#/blabla">其他</a></li>
        </ul>
         <!-- 内容将替换ng-view的标签 -->
        <div ng-view></div>
        <script src="js/angular-1.3.0.js"></script>
        <script src="http://apps.bdimg.com/libs/angular-route/1.3.13/angular-route.js"></script>
        <script>
            // 依赖ngRoute
            angular.module('routingDemoApp',['ngRoute'])
            //要注入$routeProvider
            .config(['$routeProvider', function($routeProvider){
                $routeProvider
                .when('/',{template:'这是首页页面'})
                .when('/computers',{template:'这是电脑分类页面'})
                .when('/printers',{template:'这是打印机页面'})
                .otherwise({redirectTo:'/'});
            }]);
        </script>
    </body>
</html>

依赖注入

用过spring的人都知道什么是依赖注入,依赖注入就是弄一个中央的容器,当你需要你就注入
AngularJS 提供很好的依赖注入机制。以下5个核心组件用来作为依赖注入:
1. value
2. factory
3. service
4. provider
5. constant
下面用一个简单的乘方例子来演示

<html>
   <head>
      <meta charset="utf-8">
      <title>AngularJS  依赖注入</title>
   </head>  
   <body>
      <h2>AngularJS 简单应用</h2>
      <div ng-app = "mainApp" ng-controller = "CalcController">
         <p>输入一个数字: <input type = "number" ng-model = "number" /></p>
         <button ng-click = "square()">X<sup>2</sup></button>
         <p>结果: {{result}}</p>
      </div>
      <script src="js/angular-1.3.0.js"></script>
      <script>
         var mainApp = angular.module("mainApp", []);
         // 使用provider的方法创建service  factory
         mainApp.config(function($provide) {
            $provide.provider('MathService', function() {
               this.$get = function() {
                  var factory = {};
                  factory.multiply = function(a, b) {
                     return a * b;
                  }
                  return factory;
               };
            });
         });
         // 使用factory的方法创建service  factory
         // mainApp.factory('MathService', function() {
         //    var factory = {};
         //    factory.multiply = function(a, b) {
         //       return a * b;
         //    }
         //    return factory;
         // });
         // 在 service 中注入 factory "MathService"
         mainApp.service('CalcService', function(MathService){
            this.square = function(a) {
               return MathService.multiply(a,a);
            }
         });     
         //设置一个值
         mainApp.value("defaultInput", 5);
         // 在controller中注入$scope,CalcService和defaultInput,因为scope是angular里面的属性,所以要加上$
         mainApp.controller('CalcController', function($scope, CalcService, defaultInput) {
            $scope.number = defaultInput;
            $scope.result = CalcService.square($scope.number);
            $scope.square = function() {
                //调用service的方法
               $scope.result = CalcService.square($scope.number);
            }
         });  
      </script>
   </body>
</html>

Angularjs是一个很优秀且前卫的js库,掌握了它,开发的效率会更加高效,业务逻辑也更加的清晰,而且它吸收了很多流行后端框架的思想,所以后端人员学习起来成本也是相当的低,Angularjs是全栈工程师一个不错的选择

    原文作者:饥渴计科极客杰铿
    原文地址: https://www.jianshu.com/p/2715cbdca9fa
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞