angular directive scope匿名函数_贝程学院:Angular课程学习笔记(四)

d7c79842bbf4b5adbcd7dddb041df3ab.png

10.angular中的$location对象

angular中的$location对象(其实就是window.location的一个封装)可以用来解析浏览器地址栏中的URL。

10.1、$location对象最常用的方法:url()

$location.url()可以获取到地址栏中#后面的内容,这让我们在做ajax处理时非常有用。

 <body ng-app="location" ng-controller="locationController">
	<div>地址栏中的hash部分是:<strong>{{urlhash}}</strong></div>
     <script type="text/javascript" src="bangular.js"></script>
     <script type="text/javascript">
             var app = angular.module('location', []);
 			app.controller("locationController", ["$scope","$location" ,function ($scope,$location){
                $scope.urlhash = $location.url();
                //将$location赋值给$scope是为了可以监视$location
                $scope.location = $location;
                $scope.$watch('location.url()', function (){
                    $scope.urlhash = $location.url();
                })
            }]);
    </script>

11、angular中的service(服务)

在初学angular的时候我们的业务逻辑都是堆在controller和$scope中的,controller这一层是很薄的,出于内存性能的考虑,controller只在需要的时候才会初始化,一旦不需要就会被抛弃。因此,每当你切换或刷新页面时angular会情况当前的controller。

通过$scope来维护数据是一种非常粗暴的方法,因为$scope容易被controller、directive、module影响,所有$scope很容易崩溃或变脏。

因此通过一种集中的途径来管理所有共享的数据,然后再通过某种方法来请求修改它,这样不仅仅会更加清晰,并且还可以应对应用的体积不断增加。另外还可以让代码保持模块化,一旦在其他项目中需要用到这个service,我们可以不用在$scope、controller、filter里找相关代码,因为所有controller、filter、$scope相关的代码都在service中。

创建service的三种方式:

  • 1)Factory
  • 2)Service
  • 3)Provider

使用service实现添加一个数据到localStorage中

11.0、未使用service实现添加数据到localStorage中

<body ng-app="app" ng-controller="appController">
	<form ng-submit="addData()">
		<input type="text" ng-model="text" placeholder="输入些什么吧!">
	</form>

	<ul>
		<li ng-repeat="value in getData()">{{value}}</li>
	</ul>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		var app = angular.module('app', []);

		//未使用service时实现往localStorage中添加数据
		app.controller("appController", ['$scope', '$window', function ($scope,$window){
			$scope._values = [];
			$scope.addData = function (){//存储数据到localStorage中
				this._values.push(this.text);
				$window.localStorage.setItem("values", $window.JSON.stringify(this._values));
				this.text = "";
			};
			$scope.getData = function (){//获取localStorage上的数据
				this._values = $window.JSON.parse($window.localStorage.getItem("values"));
				return this._values;
			};
		}]);
	</script>
</body>

11.1、创建service的第一种方式:Factory

使用Factory创建service就先手动创建一个对象,然后再把这个对象返回。在controller中注入这个service,然后再controller中就可以使用这个service了。

初始化时间:factory只有在第一次注入的时候才会初始化。

<body ng-app="app" ng-controller="appController">
	<form ng-submit="addData()">
		<input type="text" ng-model="text" placeholder="输入些什么吧!">
	</form>

	<ul><li ng-repeat="value in getData()">{{value}}</li></ul>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		var app = angular.module('app', []);
		/*在控制器中注入AppFactory,注入后在控制器函数里就可以使用service中的方法了*/
		app.controller("appController", ['$scope', 'appFactory', function ($scope,appFactory){
			console.log(appFactory)
			$scope.addData = function (){//存储数据到localStorage中
				appFactory.addData(this.text);
				this.text = "";
			};
			$scope.getData = function (){//获取localStorage上的数据
				return appFactory.getData();
			};
		}]);

		/*factory()可以用来创建一个service
			参数一:service的名字
			参数二:参数二可以是一个数组或一个函数,如果参数二为数组,那么数组中的最后一项必须是一个函数,前面的项为需要注入的对象。*/
		app.factory("appFactory", ['$window', function ($window){
		/*为什么要将values定义在外面?因为将values定义在外面,在addData()、getData()方法中操作的都是同一个对象,这样就可以做到数据双向同步的效果。*/
			var val = new Array(),
				obj = {};

			/*在这里必须返回一个对象,这个对象就是service对象*/
			obj.$val = [];
			obj.addData = function (text){
				val.push(text);
				$window.localStorage.setItem("values", $window.JSON.stringify(val));
			},
			obj.getData = function (){
				/*页面一加载进来就会访问这个getData()方法,而此时localStorage中没有值的,因此通过localStorage获取的值为null,此时如果不使用或运算的话val就会变成null,由于它是双向绑定的,一旦val变成null,那么addData()中使用的val也就变成null了,这样就会导致程序无法正常工作*/
				val =
 $window.JSON.parse($window.localStorage.getItem("values")) || [];
				return val;
			}
			return obj;

		}]);
	</script>
</body>

什么时候使用factory来创建service?

在service里面当我们仅仅需要的是一个方法和数据的集合且不需要处理复杂的逻辑的时候就可以使用factory。

11.2、创建service的第二种方式:Service

使用Service方式创建service与使用Factory差不多,只不过使用Service是将函数当做构造函数使用,不用在函数内部return一个对象,angular会自动将该函数实例化,然后在controller在注入即可。

初始化时间:service只有在第一次注入的时候才会初始化

<body ng-app="app" ng-controller="appController">
	<form ng-submit="addData()">
		<input type="text" ng-model="text" placeholder="输入些什么吧!">
	</form>
	<ul><li ng-repeat="value in getData()">{{value}}</li></ul>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		var app = angular.module('app', []);

		app.controller("appController", ['$scope', 'appService', function ($scope,appService){
			console.log(appService)
			$scope.addData = function (){//存储数据到localStorage中
				appService.addData(this.text);
				this.text = "";
			};
			$scope.getData = function (){//获取localStorage上的数据
				return appService.getData();
			};
		}]);

		/*service()可以用来创建一个service
			参数一:service的名字
			参数二:参数二可以是一个数组或一个函数,如果参数二为数组,那么数组中的最后一项必须是一个函数,前面的项为需要注入的对象。
		*/
		app.service("appService", ['$window', function ($window){
			this.$values =
 $window.JSON.parse($window.localStorage.getItem("values") || "[]");
			this.addData = function (text){
				this.$values.push(text);
				$window.localStorage.setItem("values", $window.JSON.stringify(this.$values));
			};
			this.getData = function (){
				this.$values = $window.JSON.parse($window.localStorage.getItem("values")) || [];
				return this.$values;
			};
		}]);
	</script>
</body>

什么时候使用service来创建service?

service()方法很适合使用在功能控制比较多的service里面。

11.3、创建service的第三种方式:provider

provider()是创建service最低层的方式,这也是唯一一个可以使用config()方法配置创建service的方法.

初始化时间:页面一加载就初始化,即使不注入provider,它也会实例化。

<body ng-app="app" ng-controller="appController">
	<h1>{{saySometing}}</h1>
	<form ng-submit="addData()">
		<input type="text" ng-model="text" placeholder="输入些什么吧!">
	</form>

	<ul><li ng-repeat="value in getData()">{{value}}</li></ul>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		var app = angular.module('app', []);

		app.controller("appController", ['$scope', 'appProvider', function ($scope,appProvider){
			$scope.addData = function (){//存储数据到localStorage中
				appProvider.addData(this.text);
				this.text = "";
			};
			$scope.getData = function (){//获取localStorage上的数据
				return appProvider.getData();
			};
			$scope.saySometing = appProvider.say;
		}]);

		/*provider()可以用来创建一个service
			参数一:service的名字
			参数二:参数二必须是一个函数,在该函数中不可以像使用service()一样注入对象。*/
		app.provider("appProvider", function (){
			/*在这个函数中的私有变量是可以在 app.config()函数中访问与编辑的*/
			var val = [],
			    that = this;	
			that.saySometing = "";
			/*这个this.$get是必须的,并且它必须是一个函数,在该函数中你可以传递你需要的对象。然后在该函数内部必须return一个值,可以return任何值,如果不return值那么在controller中是使用不了的*/
			this.$get = function ($window){
				return {
					addData: function (text){
						val.push(text);
						$window.localStorage.setItem("values2", JSON.stringify(val));
					},
					getData: function (){
						val =
 JSON.parse($window.localStorage.getItem("values2")) || [];
						return val;
					},
					say: that.saySometing
				};
			};
		});

		/*在app.config()中注入我们的appProvider服务对象,这里传递的服务名称必须是:创建的service的名称+"Provider"*/
		app.config(function (appProviderProvider){
			appProviderProvider.saySometing = "使用provider来创建service服务,我是在app.config()中编辑的!";
		});
	</script>
</body>

对于上面的代码我们可以分为两部分:

1)带var的(私有变量)

带var的变量和函数可以在app.config()函数中访问,因此可以在它们被其它地方访问到之前进行修改。

2)this.$get

这一部分的变量和函数是可以在任意注入了”appProvider”的控制器中进行访问的。

什么时候使用provider来创建service?

1)当我们希望在应用开始前对service进行配置的时候就可以使用provider。比如我们需要配置services在不同的环境(开发、演示、生产)里面使用不同的后端处理的时候就可以用到了

、当我们打算发布开源provider()也是首先创建service的方法,这样就可以使用配置的方式来配置services而不是将配置数据硬编码写到代码里面。

12、angular中的路由

在单页面应用(angular)程序中,我们需要根据URL的变化(其实是hash的变化)来显示不同的内容(即分配不同的资源),根据URL来决定去执行哪个模块,这个过程叫做路由。

angular中的路由属于angular框架的额外附加功能,因此我们需要单独的去加载这个路由的js文件(angular-route.js),然后以模块依赖的形式引入。

angular-route.js安装方式:

  • 1)bower:npm install angular-route --save
  • 2)npm:npm installangular-route --save

12.2、angular路由的简单使用

<body ng-app="appRoute">
	<ul>
		<li><a href="#/">首页</a></li>
		<li><a href="#module1">模块1</a></li>
		<li><a href="#module2">模块2</a></li>
	</ul>
	<!-- ng-view指令就是让路由中的内容显示在这块区域中 -->
	<div ng-view></div>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript" src="angular-route.js"></script>
	<script type="text/javascript">
	//1、在创建模块的时候需依赖angular-route模块,依赖的模块名称就叫"ngRoute"
		var appRoute = angular.module("appRoute", ["ngRoute"]);
	//2、在config中定义路由规则,要想定义路由规则必须依赖"$routeProvider"
		appRoute.config(["$routeProvider", "$locationProvider", function ($routeProvider,$locationProvider){
		/*去除angular 1.6版本中会自动在地址后面加上"#!"的问题*/
			 $locationProvider.hashPrefix(''); 
		/*when()方法就表示定义一个路由规则
			参数一:参数一表示请求的地址,其实就是hash值,即URL中#后面的部分
			参数二:参数二必须是一个对象
		*/
			$routeProvider
				.when("/",{
					/*当请求的"地址"为"/"时,会去找当前定义的控制器和视图*/
					controller: "homeController",
					template: "<h1>{{content}}</h1>"
				})
				.when("/module1",{
					controller: "module1Controller",
					templateUrl: "temp"
				})
				.when("/module2",{
					controller: "module2Controller",
					template: "<h1>{{content}}</h1>"
				})
				/*当请求的"地址"都不是上面的这些地址时会走这里*/
				.otherwise({
					redirectTo: "/"//redirectTo表示重定向到哪个地址
				});
		}]);
		//3、创建控制器,每一个路由规则(即每一个when都要对应一个控制器)
		appRoute.controller("homeController", ["$scope", function ($scope){
			$scope.content = "我是首页";
		}]);
		appRoute.controller("module1Controller", ["$scope", function ($scope){
			$scope.content = "我是模块1";
		}]);
		appRoute.controller("module2Controller", ["$scope", function ($scope){
			$scope.content = "我是模块2";
		}]);
	</script>
</body>

when()方法的参数说明:

1)controller

当访问路径为when()方法的第一个参数时,会去访问这个控制

2)template

对应路径的页面模板,会显示在ng-view处

3)templateUrl

对应模板的路径,这是去加载一个HTML文件。如:“src/list.html”

4)redirectTo

重定向到某个”地址”。这个地址必须是when()方法中的某个”地址”

5)reloadOnSearch

设置是否在只有地址改变时才加载对应的模板。search和params改变时都不会 加载模板

6)caseInsensitiveMatch

路径区分大小写

7)resolve

该属性会以键值对对象的形式给路由相关的控制器绑定服务或者值,然后把执行的 结果值或对应的服务引用注入到控制器中,如果resolve是一个promise对象, 那么会等它执行成功后再注入到控制器中,此时控制器会等待resolve中的执行 结果

12.3、angular中路由的参数及路由事件

<body ng-app="appRoute">
	<ul>
		<li><a href="#/">首页</a></li>
		<!-- 传递参数值就是在"url"后面:加上斜线然后在加上参数值即可 -->
		<li><a href="#module1/9527/zhangsan">模块1</a></li>
		<li><a href="#module2">模块2</a></li>
	</ul>
	<!-- ng-view指令就是让路由中的内容显示在这块区域中 -->
	<div ng-view></div>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript" src="angular-route.js"></script>
	<script type="text/javascript">
		var appRoute = angular.module("appRoute", ["ngRoute"]);
		appRoute.config(["$routeProvider", "$locationProvider", function ($routeProvider,$locationProvider){
			 $locationProvider.hashPrefix(''); 
			$routeProvider
				.when("/",{
					controller: "homeController",
					template: "<h1>{{content}}</h1>"
				})
				/*:id、:name表示它会接收id、name两个参数,并且这两个参数可以在控制器中获取到*/
				.when("/module1/:id/:name",{
					controller: "module1Controller",
					templateUrl: "temp"
				})
				.when("/module2",{
					controller: "module2Controller",
					template: "<h1>{{content}}</h1>"
				})
				.otherwise({
					redirectTo: "/"
				});
		}]);

		appRoute.controller("homeController", ["$scope", function ($scope){
			$scope.content = "我是首页";
		}]);
		/*要想接收到传递的参数必须在控制器中注入"$routeParams"服务,$routeParams服务对象是ngRoute模块中的*/
		appRoute.controller("module1Controller", ["$scope", "$routeParams", function ($scope, $routeParams){
			$scope.content = "我是模块1";
			/*打印结果:Object {id: "9527", name: "zhangsan"},如果在路由中没有设置参数,那么它会取url中问号后面的值*/
			console.log($routeParams);
		}]);
		appRoute.controller("module2Controller", ["$scope", function ($scope){
			$scope.content = "我是模块2";
			/*当从当前地址跳到别的地址的时候会触发$routeChangeStart事件,别的地址之间相互切换不会触发*/
			$scope.$on("$routeChangeStart", function (event,next,current){
				console.log("start");
				console.log(event)
				//这个对象包含了被点击的地址的一些信息,包括$route、参数、scope
				console.log(next)
				//这个对象包含了当前地址的一些信息,包括$route、参数、scope
				console.log(current)
			});
			/*当从别的地址跳转到当前地址的时候会触发*/
			$scope.$on("$routeChangeSuccess", function (event,next,current){
				console.log("Success");
			});
			/*在路由跳转失败后触发*/
			$scope.$on("$routeChangeError", function (event,next,current){
				console.log("Error");
			});
		}]);
	</script>
</body>

12.4、设置url参数

有时候我们在跳转页面的时候需要传递参数,并且参数是在url中的,那么在angular中该如何设置呢?我们可以使用$route.updateParam()方法来实现

<body ng-app="paramModule" ng-controller="paramModuleCtrl">
	<div>
		输入参数:<input type="text" ng-model="param" />
		<button type="button" ng-click="setParam()">设置参数至URL</button>
	</div>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript" src="angular-route.js"></script>
	<script type="text/javascript">
		;(function (angular){
			angular.module("paramModule",["ngRoute"])
				.config([
					"$routeProvider","$locationProvider",
					function ($routeProvider,$locationProvider){
						$locationProvider.hashPrefix("");
						$routeProvider.when("/movie/:id",{
							controller: "paramModuleCtrl",
							template: "<h2>{{content}}</h2>"
						})
						.otherwise({
							redirectTo: "/movie/1"
						});
				}])
				.controller("paramModuleCtrl", [
					"$scope","$route",
					function ($scope,$route){
						$scope.param = "12";
						$scope.setParam = function (){
							/*$route.updateParams()方法可以改变当前路由中的参数值,并且改变后还会自动监听hashchange事件*/
							$route.updateParams({id: $scope.param});
						}
				}]);
		})(angular);
	</script>
</body>

12.5、路由配置的顺序问题

在实际开发中我们的页面的路由可能会比较复杂,那么一旦复杂起来了就会出现路由出错的情况,如:路由1的匹配规则匹配到了路由2,本来应该走路由2的结果却走了路由1。这种情况绝不是我们想要的,那么这种情况的解决方法也比较简单,如下:

a) route1.js

;(function (angular){
	angular.module('route1', ["ngRoute"])
		.config([
			"$routeProvider","$locationProvider",
			function ($routeProvider,$locationProvider){
				$locationProvider.hashPrefix("");
				$routeProvider.when("/:category/:id",{
					controller: "route1Controller",
					template: "	<h1>{{content}}</h1>"
				});
			}
		])
		.controller("route1Controller", ["$scope",function ($scope){
			$scope.content = "我是路由1,但是现在应该是路由2执行的!";
		}]);
})(angular);

b)route2.js

;(function (angular){
	angular.module('route2', ["ngRoute"])
		.config([
			"$routeProvider","$locationProvider",
			function ($routeProvider,$locationProvider){
				$locationProvider.hashPrefix("");
				$routeProvider.when("/route2/12",{
					controller: "route2Controller",
					template: "	<h1>{{content}}</h1>"
				});
			}
		])
		.controller("route2Controller", ["$scope",function ($scope){
			$scope.content = "我是路由2";
		}]);
})(angular);

c)main.html

<body ng-app="app">
	<div ng-view></div>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript" src="angular-route.js"></script>
	<script type="text/javascript">
		;(function (angular){
			/*像这种路由1的匹配规则可以匹配路由2的,我们要想匹配不会出错那么就必须在注入依赖的时候注意顺序,如果反了那么路由就会匹配出错。如下:如果route1在前面route2在后面,那么显示出来的结果一定是"我是路由1,但是现在应该是路由2执行的!"*/
			angular.module('app', ["ngRoute","route2","route1"])
				.config([
					"$routeProvider","$locationProvider",
					function ($routeProvider,$locationProvider){
						$locationProvider.hashPrefix("");
						$routeProvider.otherwise({
							redirectTo: "/route2/12"
						});
					}
				]);
		})(angular);
	</script>
	<script src="route1.js"></script>
	<script src="route2.js"></script>
</body>

13、angular中的$http

在ng中我们可以使用$http服务直接与外部进行通信,$http服务只是简单的封装了浏览器原生的XMLHttprequest对象。

13.1、$http之$http()函数

a)data.js

[
	{"name": "张三","age": "23","gender": "男"},
	{"name": "李美","age": "21","gender": "女"},
	{"name": "李四","age": "24","gender": "男"},
	{"name": "郭芳芳","age": "22","gender": "女"}
]

b)main.html

<body ng-app="httpService" ng-controller="httpServiceCtrl">
	<table>
		<thead><tr><th>姓名</th><th>年龄</th><th>性别</th></tr></thead>
		<tbody>
			<tr ng-repeat="people in peoples">
				<td>{{people.name}}</td>
				<td>{{people.age}}</td>
				<td>{{people.gender}}</td>
			</tr>
		</tbody>
	</table>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		;(function (angular){
			angular.module("httpService", [])
				.controller("httpServiceCtrl", ["$scope","$http",
function ($scope,$http){
					$scope.peoples = [];//向视图中暴露一个数据
					/*$htpp()会返回一个promise对象,因此我们可以调用then()方法来进行回调。promise是ECMAScript6的一个新知识。使用then()来进行回调与普通的回调就在于不用写那么多的函数嵌套*/
					$http({
						url: "data.json",//请求地址
                        //请求方式,总共有get、post、put、delete、head、jsonp
						method: "post",
						/*传递的参数,该参数必须是一个json对象,它将会转成?id=sadf23的形式跟在路径后面*/
						params: {"id": "sadf23"},
                        /*发送二进制数据,用blob对象,通常在post请求时使用*/
						data: new Blob([“hello word!”],{type: “text/plan”})
					}).then(function (res){
						/*当请求成功后会执行该函数。res为得到的响应数据,不过它会被angular包装一下,包装后的结果为:
						{
							config: object,原始请求的完整设置
							data: object,响应的数据,即服务器发生给我们的数据
							headers: function (){},头信息的getter函数,可以接受一个参数用来获取对应名字的值
							status: 200,响应状态码
							statusText: "ok"响应状态文本
							}	*/
						console.log(res);
						$scope.peoples = res.data;
					},function (err){
						console.log("响应或请求失败的回调");
					});
				}]);
		})(angular);
	</script>
</body>

13.2、$http之快捷请求

在angular中快捷请求有: $http.get()、$http.post()、$http.delete()、$http.put()

13.2.1、$http快捷请求之$http.get()

a)data.js

[
	{"name": "张三","age": "23","gender": "男"},
	{"name": "李美","age": "21","gender": "女"},
	{"name": "李四","age": "24","gender": "男"},
	{"name": "郭芳芳","age": "22","gender": "女"}
]

b)main.html

<body ng-app="httpService" ng-controller="httpServiceCtrl">
	<table>
		<thead><tr><th>姓名</th><th>年龄</th><th>性别</th></tr></thead>
		<tbody>
			<tr ng-repeat="people in peoples">
				<td>{{people.name}}</td>
				<td>{{people.age}}</td>
				<td>{{people.gender}}</td>
			</tr>
		</tbody>
	</table>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		;(function (angular){
			angular.module("httpService", [])
				.controller("httpServiceCtrl", ["$scope","$http",
function ($scope,$http){
					$scope.peoples = [];
					/*如果需要缓冲http请求,那么我们可以在快捷请求的第二个参数中传入{cache: true},{cache: false}为不开启http请求缓冲,默认不开启*/
					$http.get("data.json",{cache: false})
                   .then(function (res){
						console.log(res);
						$scope.peoples = res.data;
					},function (err){
						console.log("响应或请求失败的回调");
					});
				}]);
		})(angular);
	</script>
</body>

13.3、$http之跨域请求

angular也提供了一个方法可以让我们去跨域请求--$http.jsonp(),我们都知道使用jsonp跨域都会有回调,那么在angular中它将跨域的回调都集中管理了,angular将跨域的回调存储在了angular.callback对象里,这样做的一个好处就是可以集中管理跨域回调,不会污染到全局的东西。

13.1、$http跨域之$http.jsonp()

<body ng-app="jsonp" ng-controller="jsonpCtrl">
	<h1>请打开控制台查看跨域请求得到的信息</h1>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		;(function (angular){
			var url = "https://api.douban.com/v2/movie/in_theaters";
			angular.module("jsonp", [])
				.config(function($sceDelegateProvider) {
					/*在config必须进行如下设置,否则会报:$http.jsonpBlocked loading resource from url not allowed by $sce错误*/
				   $sceDelegateProvider.resourceUrlWhitelist([
				   		//运行同资源请求
				       'self',
				       // 允许我们的网站加载这个网站中的资源。请注意*与**的区别
				       "https://api.douban.com/**"]);
				})
				.controller("jsonpCtrl", ["$scope","$http", 
function ($scope,$http){
					/*angular在请求前会自动在请求的路径后面加上callback=JSON_BACK的参数,并且在发送请求时会自动将callback=JSON_BACK转成callback=angular.callbacks._0,"callback"就是后台接收回调函数名称的键,"angular.callbacks._0"就是回调函数的名称*/
					$http.jsonp(url).when(function (data){
						/*由于豆瓣api不支持回调函数名为angular.callbacks._0的原因,会导致请求的内容是得到了,但angular还是报错了*/
						console.log(data);
					},function (){
						console.log("请求出错!");
					});
				}]);
		})(angular);
	</script>
</body>

14、angular之$apply()

我们都知道angular js的双向数据绑定是非常厉害的,视图中的值改变了会同步到数据模型,数据模型中的值改变了会同步到视图中。对于双向数据绑定在angular中有着明确的要求,就是angular只负责对发生于angular js上下文环境中的数据模型的变更会自动地响应,所以任何的modle变更都会被反映到视图中。但是如果在angular js上下文之外的任何地方修改了modle的值,angular都不会反映到视图中,如果需要反映到视图中就需要通过调用$.apply()方法来通知angular。这就像告诉angular,你修改了一些modle,希望angular帮你触发watchs来做出正确的响应。

14.1、$apply()使用方法之一及使用场景

<body ng-app="angularApply" ng-controller="angularApplyCtrl">
	<h1>1秒后输出的内容:{{text1}}</h1>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		;(function (angular){
			angular.module("angularApply", [])
				.controller("angularApplyCtrl", ["$scope",
function ($scope){
					$scope.text1 = "";
					setTimeout(function (){
						/*在这里1秒过后页面不会输出任何内容,console.log($scope.text);可以输出内容。这是因为setTimeout函数不是angular js上下文的方法,在这里改变了数据模型中的值,而angular js并不知道数据模型中的值已经被改变,因此angular也就不会将值同步到视图中*/
						$scope.text1 = "1秒过后我没有显示出来";
						console.log($scope.text1);
					}, 1000);
				}]);
		})(angular);
	</script>
</body>
<body ng-app="angularApply" ng-controller="angularApplyCtrl">
	<h1>3秒后输出的内容:{{text2}}</h1>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		;(function (angular){
			angular.module("angularApply", [])
				.controller("angularApplyCtrl", ["$scope",
function ($scope){
					$scope.text2 = "";

					setTimeout(function (){
						/*这个setTimeout方法同样也不是angular js上下文的方法,但3秒后视图中有输出。这是因为我们在这里调用了$scope.$apply方法,这个方法就相当于告诉angular数据模型中的值有改变了,请立即同步到视图中*/
						$scope.$apply(function (){
							$scope.text2 = "3秒过后我显示出来了";
							console.log($scope.text2);
						});
					},3000);
				}]);
		})(angular);
	</script>
</body>

14.2、$apply()的使用方式二

<body ng-app="angularApply" ng-controller="angularApplyCtrl">
	<h1>3秒后输出的内容:{{text2}}</h1>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript">
		;(function (angular){
			angular.module("angularApply", [])
				.controller("angularApplyCtrl", ["$scope",
function ($scope){
					$scope.text2 = "";
					setTimeout(function (){
						$scope.text2 = "3秒过后我显示出来了";
						console.log($scope.text2);
						/*直接写$scope.$apply()也是可以的,它也可以直接传入需要更新数据模型的名称,如:$scope.$apply(“text2”)*/
						$scope.$apply();
					},3000);
				}]);
		})(angular);
	</script>
</body>

14.3、$scope.$apply()与$scope.$apply(function (){})的区别

在$scope.$apply()中,我们是angular上下文的外面更新数据,如果有发生错误,angular永远不会知道。而$scope.$apply(function (){})的形式,我们传入进去的function (){}会被包裹在try{}catch(){}中,一旦有异常发生,该异常会被$exceptionHandler service处理。

1、angular设置全局变量

angular中想要设置全局变量有3种方式,第一种是js的设置全局变量的方式,angular自身有两种方式可以设置全局变量。

  • 1)通过var直接定义全局变量,这与纯js一样
  • 2)通过angularjs的constant定义全局变量
  • 3)通过angularjs的value定义全局变量

15.1、使用angular的constant定义全局变量

使用场景:constant一般用来配置一些经常使用的数据,constant属于$provider

<body ng-app="app" ng-controller="appController">
	<h2>{{content}}</h2>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript" src="angular-route.js"></script>
	<script type="text/javascript">
		;(function (angular){
			angular.module('app', ["module1"])
				/*constant()方法参数
					参数一:常量的名字
					参数二:常量值,它可以是任何类型的值
				*/
				.constant("commonData",{pageCount: 10})
				//在控制器中注入这个常量
				.controller("appController", 
					["$scope","commonData","testConstant",
						function ($scope,commonData,testConstant){
							console.log(commonData);
							$scope.content = "app模块中输出的pageCount为" + commonData.pageCount;
							testConstant.echo();
					}])
		})(angular);
		//在其他模块中使用常量
		;(function (angular){
			angular.module('module1', [])
				.service("testConstant", ["commonData",
function (commonData){
					this.echo = function (){
						console.log(commonData);
					}
				}]);
		})(angular);
	</script>
</body>

15.2、使用angular的value定义全局变量

使用场景:value一般用来注册服务对象或函数

<body ng-app="app" ng-controller="appController">
	<h2>{{content}}</h2>
	<div ng-view></div>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript" src="angular-route.js"></script>
	<script type="text/javascript">
		;(function (angular){
			angular.module('app', ["module1"])
				/*value()方法参数
					参数一:常量的名字
					参数二:常量值,它可以是任何类型的值*/
				.value("commonData",{pageCount: 10})
				//在控制器中注入这个常量
				.controller("appController", 
					["$scope","commonData","testConstant",
						function ($scope,commonData,testConstant){
							console.log(commonData);
							$scope.content = "app模块中输出的pageCount为" + commonData.pageCount;
							testConstant.echo();
					}])
		})(angular);
		//在其他模块中使用常量
		;(function (angular){
			angular.module('module1', [])
				.service("testConstant", ["commonData",
function (commonData){
					this.echo = function (){
						console.log(commonData);
					}
				}]);
		})(angular);
	</script>
</body>

15.3、constant与value的区别

  • 1)constant可以在config里注入,而value不可以
  • 2)value的值可以在其他地方修改,但constant不可以
  • 3)constant因为注册的是常量,所以它可以在其它value、factory、service 生效之前生效,简单的说就是constant可以在config的时候被注入使用
  • 4)value只支持在controller、service、factory中注入使用,而constant 可以在任何地方使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值