$state、$watch、$scope、$rootScope分别是什么?

本文详细介绍了AngularJS中的核心概念,包括作用域($scope和$rootScope)的层级关系和作用,$watch的深度监听及其优缺点,以及$state在路由中的应用。通过实例解析了这些概念在实际开发中的运用,帮助开发者更好地掌握AngularJS的精髓。
部署运行你感兴趣的模型镜像

angular之中,$state,$watch,$scope,$rootScope分别是什么?

1.背景介绍

在平时的编码中,我们总会想着有什么方法能够简化我们的工作流程,让我们只专心于业务逻辑和数据的处理,而angularjs

就为我们程序员实现了这一点。AngularJS有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。下面,我们将要讨论的就是angularJS里面的scopescopescoperootScopewatch和watch和watchstate

2.知识剖析

作用域

我们可以把angularJs里面的作用域看做为一个容器,在控制器中我们可以访问这个容器我们可以往这个容器中放入一些模型数据,在视图中我们可以通过表达式将数据展示给用户。作用域是应用在HTML(视图)和JavaScript(控制器)之间的纽带,他是一个对象,有可用的方法和属性,可应用在视图和控制器上。

rootScope与rootScope与rootScopescope

【1】当angularJS遇到ng-app指令的时候就会自动生成一个名为rootScope的作用域,该作用域就是就是angularJS的根作用域。rootScope的作用域,该作用域就是就是angularJS的根作用域。rootScopeangularJSrootScope就相当于一个全局作用域,所以我们保存在其中的东西是全局性的,在任一controller之中都能够使用

【2】当angularJS遇到controller或者一些自定义指令的时候也会自动的生成一个名为$scope的作用域scope是html和单个controller之间的桥梁,数据绑定就靠他了。

【3】scope都是scope都是scoperootScope的子作用域。

$watch

相信使用过angularjs的同学都知道,ng中有个比较重要的特点,叫做双向绑定,那么这个双向绑定是如何实现的呢?当我们在对绑定的name属性进行修改的时候,angular内部的digest循环级会执行一次,他执行的内容是检查我们的digest循环级会执行一次,他执行的内容是检查我们的digestscope作用域的内容与上次执行digest循环的时候是否有变化,若有变化就执行digest循环的时候是否有变化,若有变化就执行digestwatch()方法绑定的处理函数。从而达到了监听作用域属性的效果。

$watch(watchExpression,listener,objectEquality);

watchExpression,需要监控的表达式

listener,处理函数,函数参数如下function(newValue,oldValue,scope)

objectEquality,是否深度监听,如果设置为true,它告诉Angular检查所监控的对象中每一个属性的变化.如果你希望监控数组的个别元素或者对象的属性而不是一个普通的值,那么你应该使用它

$state

在ajax技术发展普及之后,因为其不会留下历史记录方便浏览器访问和对于seo不友好的特点,一个新技术应运而生:路由,$state就是路由中的一项服务。

$state.go()

state.go()方法可以产生与a链接一样的效果,可以将此方法绑定给一个button按钮,然后在按钮的点击事件中国执行state.go()方法可以产生与a链接一样的效果,可以将此方法绑定给一个button按钮,然后在按钮的点击事件中国执行state.go()abuttonstate.go(),就可以跳转到相应的页面。

stateParams状态参数在上面提及使用stateParams状态参数在上面提及使用stateParams使stateparams来提取在url中的不同参数。该服务的作用是处理url的不同部分。例如,当上述的inbox状态是这样时:url:’/inbox/:inboxId/messages/{sorted}?from&to’//当用户访问者链接时:’/inbox/123/messages/ascending?from=10&to=20’

$stateParams对象的值为:{inboxId:‘123’,sorted:‘ascending’,from:10,to:20}

详细讲解

3.常见问题

watch的深度监听是什么意思呢?有什么优缺点呢?

4.解决方案

watch在对待原始类型和引用类型会有不同的处理方式,这就要首先说一说watch在对待原始类型和引用类型会有不同的处理方式,这就要首先说一说watchwatch函数的第三个参数。在前面的例子中,我们知道,watch函数有接收两个参数,第一个参数是需要监视的对象,第二个参数是在监视对象发生变化时需要调用的函数,实际上watch函数有接收两个参数,第一个参数是需要监视的对象,第二个参数是在监视对象发生变化时需要调用的函数,实际上watchwatch还有第三个参数,它在默认情况下是false。在默认情况下,即不显式指明第三个参数或者将其指明为false时,我们进行的监视叫做“引用监视”。引用监视的原词的“referencewatch”,它的意思是只要监视的对象引用没有发生变化,就不算它发生了变化。具体来说,在上面的例子中,只要是items的引用没有发生变化,就算items中的一些属性发生了变化,$watch也会当做没有看见。

如果我们将watch的第三个变量设置为true,那么此时我们进行的监视叫做“全等监视”,原词是“equalitywatch”。此时,只要watch的第三个变量设置为true,那么此时我们进行的监视叫做“全等监视”,原词是“equalitywatch”。此时,只要watchtrueequalitywatchwatch的对象有一点风吹草动,它马上就跳出来

既然全等监视这么好,那么我们为什么不直接用全等监视呢?当然,任何事情都有好的坏的两个方面,全等监视固然是好,但是它在运行时需要先遍历整个监视对象,然后在每次$digest之前使用angular.copy()将整个对象深拷贝一遍然后在运行之后用angular.equal()将前后的对象进行对比,上面的例子中因为items比较简单,因此可能性能上不会有什么差别,但是到了实际生产时,我们要面对的数据千千万万,可能因为全等监视这一个设置就会消耗大量的资源,让应用停滞不前

5.编码实战

6.扩展思考

7.参考文献

参考一:深度理解scope

参考二:原始数据类型和对象类型的区别及深度拷贝解析

8.更多讨论

1 作用域的继承方式是什么?

答: angular里面的作用域是通过原型链的方式来实现继承的。

2 $watch脏检测原理

答: scope通过watch方法向this.watchers数组中添加watcher对象(包含watchFn,listenerFn,valueEq,last四个属性)。每当watch方法向this. watchers数组中添加watcher对象(包含watchFn,listenerFn,valueEq,last四个属性)。每当watchthis.watcherswatcher(watchFn,listenerFn,valueEq,last)digest循环被触发时,它会遍历
watchers数组中添加watcher对象(包含watchFn,listenerFn,valueEq,last四个属性)。每当$digest循环被触发时,它会遍历
watchers数组,执行watcher中的watchFn,获取当前scope上某属性的值(一个watcher对应scope上一个被监听属性),然后去同watcher中的last(上一次的值)做比较,若两值不相等,就执行listenerFn。

3 怎么定义或修改$rootScope作用域的属性和方法

答: 可以将 rootScope注入到任何一个控制器的function()里面,然后在该方法里面就可以定义rootScope 注入到任何一个控制器的function()里面,然后在该方法里面就可以定义rootScopefunctionrootScope的属性和方法。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

/** * Created by wupeng5 on 2016/5/9. */ var app = angular.module("app",['ui.router','oc.lazyLoad','tableKillModule','selectModule',"select2Module"]).config(function($stateProvider,$controllerProvider,$compileProvider,$filterProvider,$provide,$urlRouterProvider,$httpProvider){ $urlRouterProvider.otherwise('login'); //引入$stateProvider对象,为动态路由做准备 app.register = { stateProvider:$stateProvider } //$locationProvider.html5Mode(true); $httpProvider.defaults.headers.put['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; $httpProvider.defaults.headers.common["Accept"] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'; $httpProvider.defaults.headers.post['X-Requested-With'] = 'XMLHttpRequest'; $httpProvider.defaults.transformRequest = [function(data) { /** * The workhorse; converts an object to x-www-form-urlencoded serialization. * @param {Object} obj * @return {String} */ var param = function(obj) { var query = ''; var name, value, fullSubName, subName, subValue, innerObj, i; for (name in obj) { value = obj[name]; if (value instanceof Array) { for (i = 0; i < value.length; ++i) { subValue = value[i]; fullSubName = name + '[' + i + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if (value instanceof Object) { for (subName in value) { subValue = value[subName]; fullSubName = name + '[' + subName + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if (value !== undefined && value !== null) { query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; } } return query.length ? query.substr(0, query.length - 1) : query; }; return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data; }]; //配合nginx处理本地开发, 服务器调式的问题(接口是跨域的) $httpProvider.interceptors.push(function($q){ return { 'request':function(config){ if(config.url.indexOf('html') == -1){ config.url = "" + config.url; } return config || $q.when(config); } } }); //注销RootScope上面的广播事件 //var deregister = $rootScope.$on("rootEvent", function(event,data) { // //}); // //$scope.$on('$destory', function() { // deregister(); // 退订事件 //}); //注册$onRootScope方法,并在执行完毕后直接销毁, 防止内存溢出 $provide.decorator('$rootScope',['$delegate',function($delegate){ Object.defineProperty($delegate.constructor.prototype,'$onRootScope',{ value:function(name,listener){ var unsubscribe = $delegate.$on(name,listener); this.$on('$destroy',unsubscribe); }, enumerable:false }); return $delegate; }]) //使用,不需要手动去销毁这个事件 //$scope.$onRootScope("key",function(){ // console.log("get key"); //}) //$rootScope.$broadcast("key",{name:1}); }); app.factory('timestampMarker', [function() { return { request: function(config) { config.requestTimestamp = new Date().getTime(); return config; }, response: function(response) { response.config.responseTimestamp = new Date().getTime(); return response; } }; }]); app.config(['$httpProvider', function($httpProvider) { $httpProvider.interceptors.push('timestampMarker'); }]); //$http.get('xxxx').then(function(response) { // var time = response.config.responseTimestamp - response.config.requestTimestamp; // console.log('The request took ' + (time / 1000) + ' seconds.'); //}); //当路由变化的时候触发 app.run(function($rootScope,$templateCache) { $rootScope.isLogin = true; $rootScope.loginStyle = ""; $rootScope.$on('$stateChangeStart', function (event, current, previous) { if(current.name != "login" && $rootScope.currentState != current.name){ // console.log($rootScope.currentState); $rootScope.currentState = current.name; } //清理所有template缓存 if (typeof(current) !== 'undefined'){ $templateCache.removeAll(); } $rootScope.currentName = current.name; if($rootScope.currentName == "login"){ $rootScope.isLogin = false; $rootScope.loginStyle = "login"; $rootScope.col = ""; }else{ $rootScope.isLogin = true; $rootScope.loginStyle = ""; } }); });代码审计一下
最新发布
08-23
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值