1. 程式人生 > >angular基礎( 1.2 -- 2.0版本 )

angular基礎( 1.2 -- 2.0版本 )

教程推薦位置:http://www.angularjs.net.cn/tutorial/

本人是比較傾向《angular權威教程》和angular手冊結合的方式學習。

除錯工具極力推薦:ng-inspector

1、資料繫結

angular資料繫結的兩個方式:(1)ng-bind指令(2)差值表示式(3)ng-model雙向資料繫結

ng-bind和差值表示式都可以寫簡單的js表示式,ng-model只能繫結變數名。

ng-bind 和 ng-cloak 可以迴避閃爍問題(插值表示式在剛剛載入時顯示在頁面上)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>資料繫結</title>
  <script src="angular.js"></script>
</head>
<body>
  <!-- ng-app指定angular作用域  ng-init初始化資料值 -->
  <div ng-app="" ng-init="name='ion';pwd=123456;istrue=true">
    <input type="text" ng-model="name">
    <!-- 注意ng-bind會拿name覆蓋掉標籤內的所有內容 -->
    <div ng-bind="istrue?name:''">我叫:xxx</div>
    <div>我叫:{{name}}</div>
  </div>
</body>
</html>

<!-- 可以通過控制檯-->

2、資料迴圈

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>資料迴圈</title>
  <script src="angular.js"></script>
</head>
<body>
  <div ng-app="" ng-init="items=[2,5,3,2];json={'a':1,'b':2,'c':3}">
    <ul>
      <!-- track by 指定唯一key。
        angular出於效能考慮需要資料和檢視有一一對應的關係,這裡陣列出現重複資料不指定唯一key會報錯 -->
      <!-- 使用track by 也會導致刪除陣列一個元素後$index全部發生了改變,檢視又要重新渲染 -->
      <li ng-repeat="(index,item) in items track by $index">{{index}}-{{item}}</li>
    </ul>
    <!-- 另一點值得注意的就是當item是陣列或者物件時即使內容相同也不需要指定唯一key,因為陣列或物件的即使內容相同,當時其都是new Array或者new Object出來的新物件,並不相等,如下程式碼測試: -->
      <button onclick="check0()">button0</button>
      <button onclick="check1()">button1</button>
      <button onclick="check2()">button2</button>
      <button onclick="check3()">button3</button>

      <ul>
        <!-- 這裡不能用$Index,因為這個是下標順序 -->
        <li ng-repeat="(key,value) in json">{{key}}-{{value}}</li>
      </ul>
  </div>

  <script>
      function check0(){
        alert("1==1:"+(1==1)); //true
      }
      function check1(){
        alert("'a'=='a':"+('a'=='a')); //true
      }
      function check2(){
        alert("[1,2,3]==[1,2,3]:"+([1,2,3]==[1,2,3])); //false
      }

      function check3(){
        alert('{"name":"ion","age":22}=={"name":"ion","age":22}:'+({"name":"ion","age":22}=={"name":"ion","age":22}));  //false
      }
  </script>
</body>
</html>

3、ng環境與js環境

(1)ng環境與js環境不互通

<!DOCTYPE html>
<html lang="en" ng-app="">
<head>
  <meta charset="UTF-8">
  <title>ng環境與js環境不互通</title>
  <script src="angular.js"></script>
</head>
<body ng-init="a=2">
    <input type="text" ng-model="a">
    <input type="button" value="輸出" onclick="showmsg()">
    <script>
      function showmsg() {
        console.log(a);  //Uncaught ReferenceError: a is not defined
      }
    </script>
</body>
</html>

(2)ng事件(用法和js相似)

  • ng-click
  • ng-dbl-click
  • ng-mousedown
  • ng-mouseenter
  • ng-mouseleave
  • ng-mousemove
  • ng-keydown
  • ng-keyup
  • ng-keypress
  • ng-change
<!DOCTYPE html>
<html lang="en" ng-app="">
<head>
  <meta charset="UTF-8">
  <title>ng事件</title>
  <script src="angular.js"></script>
</head>
<body ng-init="arr=[{name:'ion'}]">
    <input type="text" ng-model="name">
    //ng事件能操作ng環境的變數
    <input type="button" value="輸出" ng-click="arr.unshift({name:name})">
    <ul>
      <li ng-repeat="json in arr">What you input is: {{json.name}}</li>
    </ul>
</body>
</html>

(3)   模組與controller    $scope作用域(打通ng環境與js環境)

<!DOCTYPE html>
<!-- 1.2用模組:將模組名寫在ng-app上 -->
<html lang="en" ng-app="test">
<head>
  <meta charset="UTF-8">
  <title>angular模組</title>
  <script src="angular.js"></script>
  <script>
    //1.1宣告模組:module的第一個引數是模組名稱,第二個引數是該模組依賴於哪些模組,是個陣列
    let mod = angular.module('test',[]);
    //2.1寫controller,一個模組中可以有多個controller
    mod.controller('ctrl1',function($scope){
      // 這裡是ng環境配置方法,方法裡面的parseInt是js環境下的函式
      $scope.parseInt = function (str){
        return parseInt(str);
      }

    });
  </script>
</head>
<!-- 2.2用controller -->
<body  ng-controller="ctrl1">
    <input type="text" ng-model="a">
    <input type="text" ng-model="b">
    <!-- 注意parseInt是js環境的函式,angular要呼叫要加到$scope域下 -->
    {{parseInt(a)+parseInt(b)}}
</body>
</html>

4、內建過濾器和自定義過濾器

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>系統過濾器</title>
</head>
<style>
  div[ng-app] div{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
  div[ng-app] div:nth-child(odd){background-color: #795548;}
}
</style>
<body>
      <div  ng-app="myApp" ng-controller="myController">
        <div>
          單價:<input type="number" ng-model="price" />    <br/>
          數量:<input type="number" ng-model="quantity" /> <br/>
          總價:{{(price*quantity) | currency}}
        </div>
        <div>
          篩選資料顯示<br/>
          <input type="text" ng-model="search" placeholder="輸入篩選條件" />
          <ul>
            <!-- 注意使用時需要加上冒號和篩選值  orderBy也是如此,相當於過濾器引數用冒號新增-->
            <li ng-repeat="item in items | filter:search">
              {{item}}
            </li>
          </ul>
        </div>
        <div>
          自定義過濾器stringMerge<br/>
          <!-- 傳參就往後面加“:[引數]”,但是注意第一個引數在管道符|前面 -->
          字元拼接:<em>{{ msg | stringMerge:'are':'god' }}</em>
        </div>
      </div>
      
      <script src="angular.js"></script>
      <script>
        var app = angular.module('myApp', []);
        app.controller('myController', ['$scope','$filter',function($scope,$filter) {
          $scope.price = 9.99;
          $scope.quantity = 2;

          $scope.items=['大黑','小紅','大白','小蘭'];

          //在JavaScript程式碼中可以通過$filter來呼叫過濾器
          $scope.msg=$filter('lowercase')('ION');
          
        }]);
        
        app.filter('stringMerge', function() { //可以注入依賴
            return function(text,text1,text2) {
              return text+" "+text1+" "+text2;
            }
        });
      </script>
</body>
</html>

 自定義過濾器判斷字元是否被包含:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="angular.js"></script>
</head>
<body>
    <div ng-app="myApp" ng-controller="myController">
        <div ng-if="surname | isInclude:name">{{'ion' | isInclude:name}}</div>
    </div>
</body>
<script>
    //將控制器寫成【name】-Controller 而不是 【name】-Ctrl是一種最佳實踐
    angular.module('myApp',[]).controller('myController',function ($scope) {
        $scope.name = 'ion luo';
        $scope.surname = 'luo';
    }).filter('isInclude',function () {
        return function (txt1,txt2) {
            if(txt2.indexOf(txt1)>-1){
                return true;
            }
            else{
                return false;
            }
        }
    });
</script>
</html>

5、內建服務和自定義服務

常見的angular內建服務有:$location、$http、$timeout()和$interval()

可以認為服務就是在angular應用的的一些函式(後兩個)或者物件(前兩個)。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>內建服務</title>
  <style>
    *{margin:0;padding: 0;}
    body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
    body p:nth-child(odd){background-color: #795548;}
  </style>
</head>
<body ng-app="myApp" ng-controller="myController">
  <p>
    $location服務用於返回當前頁面的URL地址:<br/>
    {{myUrl}}
  </p>
  <p>
    $http 是 AngularJS 應用中最常用的服務。服務向伺服器傳送請求,應用響應伺服器傳送過來的資料。<br/>
    伺服器返回:{{myDate}}
  </p>
  <p>
    $timeout 服務對應了 JS window.setTimeout 函式。<br/>
    $interval 服務對應了 JS window.setInterval 函式。<br/>
    在angular應用中最好使用angular的服務而不是js的相似功能函式,因為angular服務的支援性更好
    用法一樣,我們舉一個$timeout服務例子,5s後顯示"歡迎您"。
  </p>
</body>
<script src="angular.js"></script>
  <script>
    var app = angular.module('myApp',[]);
    app.controller('myController',['$scope','$location','$http','$timeout',function($scope,$location,$http,$timeout){
      // $location服務用於返回當前頁面的URL地址 
      $scope.myUrl = $location.absUrl();

      // $http 是 AngularJS 應用中最常用的服務。服務向伺服器傳送請求,應用響應伺服器傳送過來的資料。
      $http.get('welcome.php').then(function(response){
        $scope.myDate = response.date;
      },function(){
        $scope.myDate = "返回資料失敗!";
      });

      // $timeout 服務對應了 JS window.setTimeout 函式。
      //$interval 服務對應了 JS window.setInterval 函式。
      $timeout(function(){
        alert("歡迎您!");
      },5000);
    }]);
  </script>
</html>

自定義物件服務

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>自定義服務</title>
  <style>
    *{margin:0;padding: 0;}
    body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
  </style>
</head>
<body ng-app="myApp" ng-controller="myController">
  <p>
    自定義服務:用於將十進位制數字轉化成十六進位制<br/>
    <!-- 注意這裡更改input的值不會更新hex的值 -->
    <input type="number" ng-model="decimalism"><br/>
    {{ decimalism }}的十六進位制為:{{ hex }}
  </p>
</body>
<script src="angular.js"></script>
  <script>
    var app = angular.module('myApp',[]);
    //自定義物件服務
    app.service('hexafy',function(){
      this.myFun = function(param){
        return param.toString(16);
      }
    });

    app.controller('myController',function($scope,hexafy){
      $scope.decimalism = 50;
      $scope.hex = hexafy.myFun($scope.decimalism);
    });
  </script>
</html>

6、$http服務

get和post請求的簡寫格式:

$http.get('/someUrl', config).then(successCallback, errorCallback);
$http.post('/someUrl', data, config).then(successCallback, errorCallback);

7、依賴注入

AngularJS 提供很好的依賴注入機制。以下5個核心元件用來作為依賴注入:

  • (1)value

Value 是一個簡單的 javascript 物件,用於向控制器傳遞值(配置階段):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>依賴注入</title>
  <style>
    *{margin:0;padding: 0;}
    body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
  </style>
</head>
<body ng-app="myApp" ng-controller="myController">
  <p>
    {{ number }}
  </p>
</body>
<script src="angular.js"></script>
<script>
  var app = angular.module('myApp',[]);
  //// 建立 value 物件 "defaultValue" 並傳遞資料
  app.value('defaultValue',5);
  //將 defaultValue 注入控制器
  app.controller('myController',function($scope,defaultValue){
    $scope.number = defaultValue;
  });   
</script>
</html>
  • (2)service
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>依賴注入</title>
  <style>
    *{margin:0;padding: 0;}
    body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
  </style>
</head>
<body ng-app="myApp" ng-controller="myController">
  <p>
    {{ number }}
  </p>
</body>
<script src="angular.js"></script>
<script>
  var app = angular.module('myApp',[]);
  //定義服務'calcService',該服務中有個方法square返回一個數字的平方
  app.service('calcService',function(){
    this.square = function(a){
      return a*a;
    }
  });
  //將服務注入控制器
  app.controller('myController',function($scope,calcService){
    $scope.number = calcService.square(5);
  });   
</script>
</html>
  • (3)factory

factory 是一個函式用於返回值。在 service 和 controller 需要時建立。也就是說可以引入到service或者controller。通常我們使用 factory 函式來計算或返回值。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>依賴注入</title>
  <style>
    *{margin:0;padding: 0;}
    body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
  </style>
</head>
<body ng-app="myApp" ng-controller="myController">
  <p>
    {{ number }}
  </p>
</body>
<script src="angular.js"></script>
<script>
  var app = angular.module('myApp',[]);
  //建立一個 factory 'MathService'用於計算兩個數字的乘積
  app.factory('MathService',function(){
    var factory = {};

    factory.multiply = function(a,b){
      return a*b;
    }

    return factory;
  });
  //在service中注入factory,當然controller注入也可以
  app.service('calcService',function(MathService){
    this.multi = function(a,b){
      return MathService.multiply(a,b);
    }
  });
  //再將服務注入控制器
  app.controller('myController',function($scope,calcService){
    $scope.number = calcService.multi(5,6);
  });   
</script>
</html>
  • (4)constant

constant(常量)用來在配置階段傳遞數值,注意這個常量在配置階段是不可用的。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>依賴注入</title>
  <style>
    *{margin:0;padding: 0;}
    body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
  </style>
</head>
<body ng-app="myApp" ng-controller="myController">
  <p>
    {{ number }}
  </p>
</body>
<script src="angular.js"></script>
<script>
  var app = angular.module('myApp',[]);
  //宣告一個常量
  app.constant('constValue','5');
  //將常量注入控制器
  app.controller('myController',function($scope,constValue){
    $scope.number = constValue;
  });   
</script>
</html>
  • (5)provider

AngularJS 中通過 provider 建立一個 service、factory等(配置階段)。Provider 中提供了一個 factory 方法 get(),它用於返回 value/service/factory。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>依賴注入</title>
  <style>
    *{margin:0;padding: 0;}
    body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
  </style>
</head>
<body ng-app="myApp" ng-controller="myController">
  <p>
    {{ number }}
  </p>
</body>
<script src="angular.js"></script>
<script>
  var app = angular.module('myApp',[]);
  // 配置service/factory
  app.config(function($provide) {
   $provide.provider('MathService', function() {
      this.$get = function() {
         var factory = {};  
         
         factory.multiply = function(a, b) {
            return a * b; 
         }
         return factory;
      };
    });
  });
  //將MathService注入控制器
  app.controller('myController',function($scope,MathService){
    $scope.number = MathService.multiply(5,6);
  });   
</script>
</html>

8、路由

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>AngularJS 路由例項 - 菜鳥教程</title>
<script src="angular.js"></script>
<script src="https://cdn.bootcss.com/angular.js/1.7.0/angular-route.min.js"></script>
</head>
<body ng-app='routingDemoApp'>
 
    <h2>AngularJS 路由應用</h2>
    <ul>
        <li><a href="#!/">首頁</a></li>
        <li><a href="#!/computers">電腦</a></li>
        <li><a href="#!/printers">印表機</a></li>
        <li><a href="#!/blabla">其他</a></li>
    </ul>
     
    <div ng-view></div>
    <script>
        angular.module('routingDemoApp',['ngRoute'])
        .config(function($routeProvider){
            $routeProvider
            .when('/',{template:'這是首頁頁面'})
            .when('/computers',{template:'這是電腦分類頁面'})
            .when('/printers',{template:'這是印表機頁面'})
            .otherwise({redirectTo:'/'});
        });
    </script>
</body>
</html>

路由配置時設定物件:

AngularJS 路由也可以通過不同的模板來實現。

$routeProvider.when 函式的第一個引數是 URL 或者 URL 正則規則,第二個引數為路由配置物件。

路由配置物件語法規則如下:

$routeProvider.when(url, {
    template: string,
    templateUrl: string,
    controller: string, function 或 array,
    controllerAs: string,
    redirectTo: string, function,
    resolve: object<key, function>
});

引數說明:

  • template:

    如果我們只需要在 ng-view 中插入簡單的 HTML 內容,則使用該引數:

    .when('/computers',{template:'這是電腦分類頁面'})
  • templateUrl:

    如果我們只需要在 ng-view 中插入 HTML 模板檔案,則使用該引數:

    $routeProvider.when('/computers', {
        templateUrl: 'views/computers.html',
    });

    以上程式碼會從服務端獲取 views/computers.html 檔案內容插入到 ng-view 中。

  • controller:

    function、string或陣列型別,在當前模板上執行的controller函式,生成新的scope。

  • controllerAs:

    string型別,為controller指定別名。

  • redirectTo:

    重定向的地址。

  • resolve:

    指定當前controller所依賴的其他模組。

9、元件通訊

(1)通過公共服務

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body ng-app="myApp">
    <directive1></directive1>
    <directive2></directive2>
</body>
<script src="angular.js"></script>
<script>
    var app = angular.module('myApp',[]);
    //公共物件服務
    app.service('shareService',function () {
        this.names = [];
        this.addName = function(name){
            this.names.push(name);
        }
    });
    //元素指令1,通過公共服務新增輸入值到公共服務names陣列
    app.directive('directive1',function(shareService){
        return {
            restrict:"E",
            template:"name: <input type='text' ng-model='new_name'/><br/><button ng-click='addName()'>Add</button>",
            link:function (scope,element,attrs) {
                scope.addName = function () {
                    if(scope.new_name){
                        shareService.addName(scope.new_name);
                    }
                }
            }
        }
    });
    //元素指令2,通過公共服務讀取通過服務裡面的names值
    app.directive('directive2',function (shareService) {
        return {
            restrict:"E",
            template:"<ul><li ng-repeat='list in lists'>{{list}}</li></ul>",
            link:function (scope,element,attrs) {
                scope.lists = shareService.names;
            }
        }
    });
    
</script>
</html>

(2)通過link的attrs實現同一個dom下元件通訊

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body ng-app="myApp">
    <directive1 directive2></directive1>
</body>
<script src="angular.js"></script>
<script>
    <!--
    每個directive在定義的時候都有一個link函式,函式簽名的第三個引數是attrs,代表在該directive上面的
所有atrributes陣列,attrs提供了一些方法,比較有用的是$set和$observe,前者可以自定義attr或修改已經有
的attr的值,後者可以監聽到該值的變化。利用這種方式,我們可以讓在位於同一個dom元素上的兩個directive進
行通訊,因為它們之間共享一個attrs陣列。
    -->
    var app = angular.module('myApp',[]);

    app.directive('directive1',function(){
        return {
            restrict:"E",
            template:"<span>{{ time | date:'yyyy-MM-dd HH:mm:ss'}}</span>",
            link:function (scope,element,attrs) {
                attrs.$observe('showValue',function (newValue) {
                    scope.time = newValue;
                });
            }
        }
    });

    app.directive('directive2',function ($interval) {
        return {
            restrict:"A",
            link:function (scope,element,attrs) {
                let defInterval = $interval(function () {
                    attrs.$set("showValue",new Date().getTime());
                },1000);

                scope.$on('$destory',function(){
                    $interval.cancel(defInterval);
                });
            }
        }
    });

</script>
</html>

10、系統指令

全部angular系統指令可見angular參考手冊,http://www.runoob.com/angularjs/angularjs-reference.html。下面介紹些常用系統指令:

(1)ng-class 和 ng-style

<!DOCTYPE html>
<html ng-app="">
<head>
<meta charset="utf-8">
<title>常見系統指令</title>
<script src="angular.js"></script>
<style>
    .container{width:100px;height:100px;background-color:yellow}
    .box{display: inline-block; }
</style>
</head>
<!-- 注意ng-style裡面的屬性兩個單詞需要連寫並且後首字母大寫 -->
<body ng-init="a='width:100px;height:100px;background-color:red';
               b={width:'100px',height:'100px',backgroundColor:'blue'};
               c='container box';
               d=['container','box']">

    <div style="{{ a }}"></div>

    <div ng-style="b"></div>

    <div class="{{ c }}"></div>

    <div ng-class="d"></div>

</body>
</html>

效果:

(2)ng-switch

該指令和 ng-if 一樣當滿足條件才渲染到HTML中。(注意 ng-if 沒有 ng-else 指令來做if-else條件結構,需要時使用ng-switch)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>常見系統指令</title>
<script src="angular.js"></script>
</head>
<body ng-app="">
  <select ng-model="site">
    <option value="taobao">淘寶</option>
    <option value="zhihu">知乎</option>
    <option value="jingdong">京東</option>
  </select>


  <div ng-switch="site">
    <div ng-switch-when="taobao"><h1>淘寶</h1></div>
    <div ng-switch-when="zhihu"><h1>知乎</h1></div>
    <div ng-switch-when="jingdong"><h1>京東</h1></div>
    <div ng-switch-default><h1>請選擇 >>>>>></h1>  </div>
  </div>
</body>
</html>

(3) ng-bind-html 和 $sce.trustAsHtml()

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
  <meta charset="UTF-8">
  <title>ng-bind-html和$sce</title>
  <script src="angular.js"></script>
</head>
<body ng-controller= "myController">
  <div ng-bind-html="a"></div>
</body>
<script>
  var app = angular.module('myApp',[]);
  app.controller('myController',function($scope,$sce){
    $scope.a = $sce.trustAsHtml("歡迎來到<a href='https://blog.csdn.net/ion_L' target='_blank'>ion的部落格</a>");
  });
</script>
</html>

 注意,低版本的angluar可以直接繫結HTML程式碼,但是在anglar1.6.4之後必須加上$sce才可以,否則會出現如下報錯。

關於$sce的具體內容見:https://www.cnblogs.com/xing901022/p/5100551.html

11、Angular概念圖