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是全栈工程师一个不错的选择

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 通过AngularJS仿豆瓣一刻的案例:https://github.com/zhongxiaolian/doub...
    中小恋阅读 1,749评论 1 21
  • AngularJS是什么?AngularJs(后面就简称ng了)是一个用于设计动态web应用的结构框架。首先,它是...
    200813阅读 1,583评论 0 3
  • AngularJS AngularJS概述 介绍 简称:ng Angular是一个MVC框架 其他前端框架: Vu...
    我爱开发阅读 2,330评论 0 8
  • 一、介绍 AngularJS是一款由Google公司开发维护的前端MVC框架,其克服了HTML在构建应用上的诸多不...
    福尔摩鸡阅读 736评论 0 2
  • 白雪沉默地坐在车后座,通过后视镜看坐在驾驶座上抽烟的女人。 女人长得很养眼,在香烟朦胧的烟雾中像一朵曼珠沙华被怨灵...
    Diedorkce阅读 448评论 1 1