基础 - AngularJS

AngularJS
基于JS的一前端框架,产生于2009年
官方网址    https://www.angularjs.org/

客户端模板
把数据和模板先发送到客户端再装配

MVC设计模式
Model        承载数据,对象的属性
View         展示数据,即DOM
Controller   应用逻辑,即JS

数据绑定 又称MVVM
自动同步model与view之间的数据
这样,只要改动了一方,另一方就会同步

依赖注入
B的实现需要A,叫做B依赖A,A注入B
通常,将A做为参数传递,使A成为全局变量
依赖注入,不需要创建依赖而获取需要的东西

  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<!--angularjs-->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
</body>
</html>

  

ng-app指令
说明Angular可以管理的范围

  

<body>
    
    <!--angularjs-->
    <script type="text/javascript" src="//cdn.bootcss.com/angular.js/1.2.10/angular.min.js"></script>
    <!--自定义-->
    <script type="text/javascript" src="js/xiezi.js"></script>
</body>

  

表达式 {{ }}
angular表达式通过$parse服务解析执行
angular表达式的属性求值是对于scope的,JS表达式的属性求值是对于window的
angular表达式的表达式求值对于undefined和null是宽容的,
JS表达式的表达式求值对于undefined和null产生NullPointerExceptions错误异常
angular表达式没有流程控制语句,JS表达式含有流程控制语句
angular表达式可以将表达式结果传入过滤器链

  

<!--
数据绑定模型name
view与model是双向绑定的
view改变值,model对应的改变
model改变,view值对应的改变
-->
<input type="text" ng-model="name" />
<input type="text" ng-model="name" />
<!--输出模型name-->
{{name}}

  

<body>
    <div ng-app="" >
        <div ng-controller="firstController" >
            <input type="text" ng-model="name">
        </div>
    </div>
    <!--angularjs-->
    <script type="text/javascript" src="//cdn.bootcss.com/angular.js/1.2.10/angular.min.js"></script>
    <!--自定义-->
    <script type="text/javascript" src="js/xiezi.js"></script>
</body>

  

/**
 *
 * @param $scope 依赖注入,参数名不可改变,作用域
 */
function firstController ($scope) {
    $scope.name = "菲尔";
}

  

ng-bind 等待angularjs加载完再显示model数据
    <input type="text" ng-model="name"> 
    <p ng-bind="name"></p>

  

多个作用域
加载时,外部作用域下的模型数据可以传递给内部的作用域,优先选择内部自己的作用域模型数据
加载完,外部作用域下的模型数据不可以传递给内部的作用域
加载完,内部作用域下的模型数据不可以传递给外部的作用域

  

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

  

/**
 *
 * @param $scope 依赖注入,参数名不可改变,作用域
 */
function firstController ($scope) {
    $scope.name = "菲尔";
}
function secondController ($scope) {
    console.log($scope);
}

  

 

Angular的脏检查
复制一份参照,检查时如果数据有差别,即时同步数据
绑定HTML的对象,被列为检查对象
检查对象的属性,被列为检查属性
初始化时,为每个检查属性添加一个监听watcher

  

$apply()底层的实现流程
$scope.$apply()进入上下文,
$eval()解析表达式,
$rootScope.$digest()执行脏检查
注意,$scope.$apply()不传参的话,检查所有监听元素

  

/**
 *
 * @param $scope 依赖注入,参数名不可改变,作用域
 */
function firstController ($scope) {
    setInterval(function () {
        $scope.$apply(function () {
            $scope.name = new Date();
        });
    },1000);
}

  

模型改变即时刷新view

  

function secondController ($scope) {
    $scope.$watch("name", function (newValue,oldValue) {
       console.log(newValue,oldValue);
    },true);
}

  

/**
 * 购物车
 */

  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--BootstrapCSS-->
    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" >
</head>
<body ng-app>

    <div class="container" ng-controller="funCarController">
        <p ng-hide="car.length">您的购物车清空了</p>
        <table class="table" ng-show="car.length">
            <thead>
                <tr>
                    <th>序号</th>
                    <th>名字</th>
                    <th>数量</th>
                    <th>单价</th>
                    <th>总价</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="item in car">
                    <td>{{item.id}}</td>
                    <td>{{item.name}}</td>
                    <td>
                        <button type="button" class="btn btn-primary" ng-click="funReduce(item.id)">-</button>
                        <input type="text" value="{{item.quantity}}" ng-model="item.quantity" />
                        <button type="button" class="btn btn-primary" ng-click="funAdd(item.id)">+</button>
                    </td>
                    <td>{{item.price}}</td>
                    <td>{{item.price*item.quantity}}</td>
                    <td><button type="button" class="btn btn-danger" ng-click="funRemove(item.id)">移除</button></td>
                </tr>
                <tr>
                    <td colspan="2"></td>
                    <td>{{funAllQuantity()}}</td>
                    <td></td>
                    <td>{{funAllPrice()}}</td>
                    <td><button type="button" class="btn btn-danger" ng-click="car={}">清空</button></td>
                </tr>
            </tbody>
        </table>
    </div>


    <!--jquery核心代码-->
    <script src="//cdn.bootcss.com/jquery/3.1.0/jquery.js"></script>
    <!--bootstrap核心JS-->
    <script src="//cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.js"></script>
    <!--angularjs-->
    <script type="text/javascript" src="//cdn.bootcss.com/angular.js/1.2.10/angular.min.js"></script>
    <!--自定义-->
    <script type="text/javascript" src="js/xiezi.js"></script>
</body>
</html>

  

function funCarController($scope) {
    $scope.car = [
        {
            id : 001,
            name : "WeWeZhang",
            quantity : 5 ,
            price : 111
        },
        {
            id : 002,
            name : "WeWeZhang",
            quantity : 3 ,
            price : 222
        },
        {
            id : 003,
            name : "WeWeZhang",
            quantity : 2 ,
            price : 333
        }
    ];
    $scope.funAllPrice = function() {
        var x = 0;
        angular.forEach($scope.car,function(item) {
            x += item.quantity*item.price;
        });
        return x;
    }
    $scope.funAllQuantity = function() {
        var x = 0;
        angular.forEach($scope.car,function(item) {
            x += parseInt(item.quantity);
        });
        return x;
    }

    function funFindIndex(id) {
        var index = -1;
        angular.forEach($scope.car, function(item,key) {
            if (item.id === id) {
                index = key;    return;
            }
        });
        return index;
    }
    $scope.funRemove = function(id) {
        var index = funFindIndex(id);
        if (index == -1) return;
        $scope.car.splice(index,1);
    }
    $scope.funReduce = function(id) {
        var index = funFindIndex(id);
        if (index == -1) return;
        if ($scope.car[index].quantity<=1) {
            if(confirm("删掉此行数据")){
                $scope.funRemove(id);
            }
        }else {
            $scope.car[index].quantity--;
        }
    }
    $scope.funAdd = function(id) {
        var index = funFindIndex(id);
        if (index == -1) return;
        $scope.car[index].quantity++;
    }
    $scope.$watch("car", function(newValue,oldValue) {
        angular.forEach(newValue, function (item,key) {
            if (item.quantity<1) {
                if(confirm("数据不合法,是否置1")){
                    item.quantity=1;
                }else{
                    item.quantity=oldValue[key].quantity;
                }
            }
        })
    },true);
}

  

/**
 * 模块
 */
声明依赖关系和组装方式和启动方式

优点
声明式的启动
可以只加载需要的模块,方便单元测试
可以将第三方代码打包成代码
可以串行执行也可以并行执行,模块的执行是延迟的
可自定义模块

机制
模块提供多种机制,服务、指令、过滤器以及其它配置信息

服务机制
服务需要显式地声明依赖,使模块准确的注入服务
ng模块,angular默认的模块,内部封装了$http和$scope等服务
可以在现有的模块上自定义服务
可以自定义新的模块,再自定义服务

  

    <!--we模块-->
    <div ng-app="we">
        <div class="container" ng-controller="funCarController">
            <p ng-hide="car.length">您的购物车清空了</p>
            <table class="table" ng-show="car.length">
                <thead>
                <tr>
                    <th>序号</th>
                    <th>名字</th>
                    <th>数量</th>
                    <th>单价</th>
                    <th>总价</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                <tr ng-repeat="item in car">
                    <td>{{item.id}}</td>
                    <td>{{item.name}}</td>
                    <td>
                        <button type="button" class="btn btn-primary" ng-click="funReduce(item.id)">-</button>
                        <input type="text" value="{{item.quantity}}" ng-model="item.quantity" />
                        <button type="button" class="btn btn-primary" ng-click="funAdd(item.id)">+</button>
                    </td>
                    <td>{{item.price}}</td>
                    <td>{{item.price*item.quantity}}</td>
                    <td><button type="button" class="btn btn-danger" ng-click="funRemove(item.id)">移除</button></td>
                </tr>
                <tr>
                    <td colspan="2"></td>
                    <td>{{funAllQuantity()}}</td>
                    <td></td>
                    <td>{{funAllPrice()}}</td>
                    <td><button type="button" class="btn btn-danger" ng-click="car={}">清空</button></td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>

  

/**
 * 创建模块
 */
var oWeModule = angular.module("we",[]);

oWeModule.controller("funCarController", function ($scope) {
    $scope.car = [
        {
            id : 001,
            name : "WeWeZhang",
            quantity : 5 ,
            price : 111
        },
        {
            id : 002,
            name : "WeWeZhang",
            quantity : 3 ,
            price : 222
        },
        {
            id : 003,
            name : "WeWeZhang",
            quantity : 2 ,
            price : 333
        }
    ];
    $scope.funAllPrice = function() {
        var x = 0;
        angular.forEach($scope.car,function(item) {
            x += item.quantity*item.price;
        });
        return x;
    }
    $scope.funAllQuantity = function() {
        var x = 0;
        angular.forEach($scope.car,function(item) {
            x += parseInt(item.quantity);
        });
        return x;
    }

    function funFindIndex(id) {
        var index = -1;
        angular.forEach($scope.car, function(item,key) {
            if (item.id === id) {
                index = key;    return;
            }
        });
        return index;
    }
    $scope.funRemove = function(id) {
        var index = funFindIndex(id);
        if (index == -1) return;
        $scope.car.splice(index,1);
    }
    $scope.funReduce = function(id) {
        var index = funFindIndex(id);
        if (index == -1) return;
        if ($scope.car[index].quantity<=1) {
            if(confirm("删掉此行数据")){
                $scope.funRemove(id);
            }
        }else {
            $scope.car[index].quantity--;
        }
    }
    $scope.funAdd = function(id) {
        var index = funFindIndex(id);
        if (index == -1) return;
        $scope.car[index].quantity++;
    }
    $scope.$watch("car", function(newValue,oldValue) {
        angular.forEach(newValue, function (item,key) {
            if (item.quantity<1) {
                if(confirm("数据不合法,是否置1")){
                    item.quantity=1;
                }else{
                    item.quantity=oldValue[key].quantity;
                }
            }
        })
    },true);
});

  

/**
 * 自定义模块,自定义服务
 */
var oWeModule = angular.module("we",[], function ($provide) {
    $provide.provider("$newService", function () {
        this.$get = function () {
            return {
                message:"没理由的呢"
            }
        }
    });
});
oWeModule.controller("funCarController", function ($scope,$newService) {
    console.log($newService);
},true);

  

/**
 * 简便写法,factory可返回任意形式的数据,service只能返回对象类型
 */
var oWeModule = angular.module("we",[], function ($provide) {
    $provide.factory("$newFactory", function () {
        return "没理由的呢";
    });
    $provide.service("$newService", function () {
        return {name:"wewezhang",age:25};
    });
});

  

/**
 * 然而实际开发中,这样使用factory和service
 */
angular.module("we",[])
    .factory("$newFactory", function () {
        return "没理由的呢";
    })
    .service("$newService", function () {
        return {name:"wewezhang",age:25};
    })
    .controller("funCarController", function ($scope,$newService,$newFactory) {
        console.log($newService,$newFactory);
    },true);

  

/**
 * 多控制器之间的数据交互
 */

  

    <!--we模块-->
    <div ng-app="we">
        <div ng-controller="funFirstController">
            <input type="text" ng-model="data.message" />
        </div>
        <div ng-controller="funSecondController">
            <input type="text" ng-model="data.message" />
        </div>
    </div>

  

angular.module("we",[])
    .factory("$pubicData", function () {
        return {
            message : "WeWeZhang"
        };
    })
    .controller("funFirstController", function ($scope,$pubicData) {
        $scope.data = $pubicData;
    },true)
    .controller("funSecondController", function ($scope,$pubicData) {
        $scope.data = $pubicData;
    },true);

  

/**
 * 过滤器
 */
对数据进行格式化
筛选数据

可以直接使用在模板中
{{表达式 | 过滤器}}
{{表达式 | 过滤器 | 过滤器}}
{{表达式 | 过滤器 : 参数,参数}}

常见的过滤器
number      格式化数字,例如 {{123234456 | number}} 就是 123,234,456
currency    格式化货币,例如 {{1234| currency:"¥"}} 就是  $1234.00
date        格式化日期,例如 {{data.time | date:"yyyy年MM月dd日 HH点mm分ss秒 hh点mm分ss秒"}
    yyyy年MM月dd日 HH点mm分ss秒 hh点mm分ss秒
    2016年10月23日 15点05分51秒 03点05分51秒
    medium        Oct 23, 2016 11:25:12 AM
    short         10/23/16 11:44 AM
    fullDate      Sunday, October 23, 2016
    longDate      October 23, 2016
    mediumDate    Oct 23, 2016
    shortDate     10/23/16
    mediumTime    11:46:51 AM
    shortTime     11:48 AM
limitTo     格式化截取{{[2,3,4,5,6] | limitTo:3}} {{[2,3,4,5,6] | limitTo:-3}}
lowercase   格式化小写{{"WeWeZhang" | lowercase}}
uppercase   格式化大写{{"WeWeZhang" | uppercase}}
filter      格式化对象
{{[{name:"Zhang"},{name:"WeZhao"},{name:"WeQian"}] | filter:"We"}}
{{[{name:"Zhang"},{name:"We"},{name:"We"}] | filter:{name:"We"} }}
orderby     格式化排序     升序asc和降序desc
{{
    [{"id": 2,"name": "index02"},
        {"id": 1,"name": "index01"},
        {"id": 3,"name": "index03"}] | orderBy:'id' }}
{{
    [{"id": 2,"name": "index02"},
        {"id": 1,"name": "index01"},
        {"id": 3,"name": "index03"}] | orderBy:'id':true }}
json        格式化Josn
控制器中使用过滤器
.controller("funFirstController", function ($scope,$pubicData,$filter) {
    $pubicData.time = $filter("date")($pubicData.time,"yyyy年MM月dd日 HH点mm分ss秒 hh点mm分ss秒");
    $scope.data = $pubicData;
    console.log($filter('json')($scope.data));
},true)
自定义不带参数filter
.filter('funOrdinal', function () {
    return function (number) {
        if (isNaN(number) || number < 1) {
            return number;
        } else {
            var lastDigit = number % 10;
            if (lastDigit === 1) {
                return number + 'st'
            } else if (lastDigit === 2) {
                return number + 'nd'
            } else if (lastDigit === 3) {
                return number + 'rd'
            } else if (lastDigit > 3) {
                return number + 'th'
            }
        }
    }
})
{{777 | funOrdinal}}
自定义带参数filter
.filter('funCapitalize', function () {
    return function (input, char) {
        if (isNaN(input)) {
            var char = char - 1 || 0;
            var letter = input.charAt(char).toUpperCase();
            var out = [];
            for (var i = 0; i < input.length; i++) {
                if (i == char) {
                    out.push(letter);
                } else {
                    out.push(input[i]);
                }
            }
            return out.join('');
        } else {
            return input;
        }
    }
})
{{'seven' | funCapitalize:3}}

  

/**
 * 过滤器实例
 */

  

<!--模块-->
<div ng-app="we" class="container">
    <div ng-controller="funSampleController">
        <nav class="navbar navbar-default" role="navigation">
            <div class="container-fluid">
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                    <form class="navbar-form navbar-left" role="search">
                        <div class="form-group">
                            <input type="text" class="form-control" placeholder="Search" ng-model="search.id">
                        </div>
                    </form>
                </div>
            </div>
        </nav>
        <table class="table">
            <thead>
                <tr>
                    <th ng-click="funChangeOrder('id')" ng-class="{dropup:!order.length}">编号<span class="caret"></span> </th>
                    <th ng-click="funChangeOrder('name')" ng-class="{dropup:!order.length}">名称<span class="caret" ></th>
                    <th ng-click="funChangeOrder('price')" ng-class="{dropup:!order.length}">价钱<span class="caret" ></th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="item in data | filter:search | orderBy:order+orderType ">
                    <td>{{item.id}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.price | currency:"¥"}}</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

  

angular.module("we",[])
    .factory("$publicData", function () {
        return [
            {   id:002,
                name:"iPhone4S",
                price:2000   },
            {   id:001,
                name:"iPhone5S",
                price:3500   },
            {   id:003,
                name:"iPhone6P",
                price:6000   }
        ];
    })
    .controller("funSampleController", function ($scope,$publicData,$filter) {
        $scope.data = $publicData;
        console.log($filter('json')($scope.data));
        $scope.orderType = "id";
        $scope.order = "";
        $scope.funChangeOrder = function (string) {
            $scope.orderType = string;
            $scope.order = $scope.order.length?"":"-";
        }
    },true);

  

/**
 Controller的正确使用方法
 抽离不必要的业务到.service或.factory中,然后Controller通过依赖注入的方式使用它们
 常见的不必要的业务
 任何DOM操作,任何的表现逻辑都是不必要的,通常抽离到directive中
 任何输入格式化,通常使用formcontrols代替
 任何输出格式化过滤,通常使用filter代替
 任何无状态或有状态的controllers共享的代码,通常使用service或factory代替
 任何实例化或管理其他组件的生命周期
 */

  

    /**
     * 显式的依赖注入
     */
    .controller("funSampleController",["$scope","$filter","$publicData", function ($scope,$filter,$publicData) {
        $scope.data = $publicData;
        console.log($filter('json')($scope.data));
    }],true)

  

function funNormal($sample) {
    
}
funNormal.$inject = ["$scope"];

  

/**
 * 指令
 * 扩展HTML标签,声明式语法使用特殊的标签替换普通的标签
 * 指令的校验格式
 * 普通校验格式      ng-name
 * XML校验格式      ng:name
 * XHTML校验格式    x-ng-name
 * HTML5校验格式    data-ng-name
 * angular内置的指令
 * angular内置了多种多样的指令,例如ng-app ng-controller等
 * angular内置的指令大体可分为:渲染指令、、
 * 渲染指令
 * ng-init      初始化指令    <div ng-init="array=['we']"></div>
 * ng-bind      等待渲染指令  <div ng-bind>{{1+1}}</div>
 * ng-repeat    遍历指令
 * 其中,$index当前元素的索引 $first当前元素是否头元素 $middle当前元素是否既不是头也不是尾 $last当前元素是否尾元素
 * ng-include   <div ng-include="'sample.html'"></div>
 * 事件指令
 * 执行完事件以后,自动执行脏检查
 * $scope.funChangeOrder = function (event) {
 *     angular.element(event.target).val($scope.bState);
 * }
 * <div ng-click="funChangeOrder($event)"></div>
 * 节点指令
 * ng-style <div ng-style="{'color':'#cccccc','margin-top':'50px'}">Sam</div>
 * ng-class <div ng-class="{clsssname:isTrue}"></div>
 * ng-class-odd奇数   ng-class-even偶数
 * ng-show显示或ng-hide隐藏 <div ng-show="state"></div>
 * ng-switch on="state" ng-switch-when="true" 或 "false"
 * ng-src ng-href 采用延迟加载机制,类似ng-bind
 * ng-if  条件判断
 * 自定义指令
 */
angular.module("we",[],["$compileProvider",function($compileProvider){
    $compileProvider.directive("zwCustomTag", function () {
        return{
            /**
             * A属性
             * C类
             * E元素     <zw-custom-tag></zw-custom-tag>
             * M注释
             **/
            restrict:"ACEM",
            template:"<div>Sample</div>",
            replace:true
        }
    });
}])
    .directive("zwCustomTag", function () {
        return {
            /**
             * A属性
             * C类
             * E元素     <zw-custom-tag></zw-custom-tag>
             * M注释
             **/
            restrict: "ACEM",
            template: "<div>Sample</div>",
            replace: true
        }
    });

  

posted @ 2016-10-19 19:33  WeWeZhang  阅读(301)  评论(0编辑  收藏  举报