未加星标

angular开发中问题记录--启动过程初探

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二05 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

公司一些管理后台的前端页面,使用的是angular开发的,得益于angular的双向绑定和模块化controller使得构建pc端的CRUD应用简单了不少。angular有很多比较难理解的概念,上手起来没有vue简单,不过对着模板项目、看看tutorial、阅读项目代码再仿照项目代码写一些业务功能还是可行的。如果想要用到一些高级功能那就要下一定功夫学习才行。

遇到的问题

在开发的时候遇到了这么一个问题,先上代码

'use strict'; var domain = 'http://localhost:1337'; //开发环境下的服务端地址, var MY_DOMAIN = 'http://production.com'; // 生成环境的网站地址 angular.module('adminApp').run(function($location) { if ($location.host() !== 'localhost') { domain = MY_DOMAIN; } }) .constant('myConfig', { host: domain, domain: domain, api: this.domain + '/admin', //项目中请求服务端异步获取数据的接口 }

上面的代码,乍一看是自动切换生产和开发环境的服务端地址,可是当部署之后发现这段代码好像并没有生效,domain始终是' http://localhost:1337 ',并没有通过判断host而被赋值为MY_DOMAIN。

在没有对angular的运行机制有所了解的情况下,我会认为代码会自上而下的执行,这样在.constant的代码执行之前,会先执行.run里面的方法。然而代码的最终执行结果表明,.constant内的代码运行应该是先于.run里面的代码。于是阅读angular的文档来找找原因。

constant和run是什么

angular比较核心的一个概念就是 依赖注入 ,angular的模块化以及模块间的依赖管理都是基于此的。而这些依赖都是从哪里来的或者怎么自建一些依赖呢?这就需要自己定义一些 Providers ,angular提供了5种Provider recipe(恕我不知道怎么翻译这个概念):factory、service、value、constant、provider,这里我们只关心constant。官方文档描述constant是用来为配置阶段(config phase)和运行阶段(run phase)提供没有依赖的简单对象,也就是说我们在constant里面定义的对象或基本类型可以在run和config里面注入:

angular.module('adminApp') .constant('myObj', { name: 'angular' }) .constant('myStr', 'hello') .config(function(myObj) { console.log(myObj.name) // angular }) .run(function(myStr) { console.log(myStr) //hello })

那什么是运行和配置阶段呢?官方文档这样说:

A module is a collection of configuration and run blocks which get applied to the application during the bootstrap process. In its simplest form the module consists of a collection of two kinds of blocks:

1. Configuration blocks - get executed during the provider registrations and configuration phase. Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.

2. Run blocks - get executed after the injector is created and are used to kickstart the application. Only instances and constants can be injected into run blocks. This is to prevent further system configuration during application run time.

上面介绍angular的模块实际上是配置块和运行块的集合,这些blocks是在angular的启动(bootstrap)过程中被添加进模块的。Configuration blocks和Run blocks可以理解为队列,一个模块可以写多个.run和.config,最后被依次添加进相应的blocks中。config只能注入provider 和constant recipe,run只能注入实例(不是providers)和constant recipe。但我测试value recipe是可以注入到run的,好吧我承认angular文档真的不好理解。

总之我觉得就一句话概况就是:constant可以理解为是angular用来为模块提供可注入的所有模块共享的常量(无依赖的简单对象或类型),并且在config和run阶段之前定义好的。 (仅仅是个人理解)

执行顺序 上面说了constant应该是在run之前被执行,可这只是程序运行的表象,为什么会这样呢,于是就搜索了一下angular的启动过程,其中这篇对启动过程的[源码分析]( http://liuwanlin.info/angular... ),给了我一些启发。

里面介绍了setupModuleLoader方法,该函数返回了一系列的API,用于Angular组织模块,注册指令、服务、控制器。


angular开发中问题记录--启动过程初探

能够看到刚才前面介绍的configBlocks和runBlocks,这里要说明的是constant使用了unshift,将constant插入到队列的首部,这也就保证了constant在配置、运行之前能够在其他所有块中被注入。

再看下loadModules方法,这个方法用于加载模块,即返回需要运行的块,之前提到的constant和provider其实就是被加入了invokequeue之中,这只是注册并没有执行,在这个函数中调用runInovequeue才真正执行生成实例,也可以看出config是在run之前运行的:


angular开发中问题记录--启动过程初探
解决问题

上面大致解释了一下constant先于run被执行的原因,这也是文章最开始写的代码没有按照预期执行的原因。知道了原因又知道.run里面可以注入已经定义的constant,那么我们就知道只要稍微改一下代码就可以得到想要的结果:

'use strict'; var domain = 'http://localhost:1337'; //开发环境下的服务端地址, var MY_DOMAIN = 'http://production.com'; // 生成环境的网站地址 angular.module('adminApp').run(function($location, myConfig) { if ($location.host() !== 'localhost') { myConfig.domain = MY_DOMAIN; myConfig.api = mzConfig.domain + '/admin'; //这里不要期望myConfig里面的domain会跟随者domain变量的变化而变化,对象一旦建立,它的属性值就是固定的了,想修改只能通过对象访问属性修改。 } }) .constant('myConfig', { host: domain, domain: domain, api: this.domain + '/admin', //项目中请求服务端异步获取数据的接口 } 参考文档:

angular providers

angular modular

dependency injection

AngularJS中几种Providers(Factory, Service, Provider)的区别

AngularJS源码阅读1:启动过程

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

主题: AngularJS数据其实模块化变量
分页:12
转载请注明
本文标题:angular开发中问题记录--启动过程初探
本站链接:http://www.codesec.net/view/483174.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(32)