摘要:前言由于在博客系统的开发中和近期工作中的前端框架主要使用因此在这里记录学习和使用的过程中遇到的一些需要记录的点。执行过程弄清楚的执行过程是很重要的,这样你才能在正确的时机做正确的事。至此,的执行过程也就告一段落了。
前言
由于在博客系统的开发中和近期工作中的前端框架主要使用 AngularJS ,因此在这里记录学习和使用 AngularJS 的过程中遇到的一些需要记录的点。特别说明,本文并非教程。
执行过程弄清楚 AngularJS 的执行过程是很重要的,这样你才能在正确的时机做正确的事。在这点上我就犯过错误,话不多说,直接上代码:
var app = angular.module("app", ["ngRoute"]); app.config([ "$routeProvider", "$http", "$q", function ($routeProvider, $http, $q) { $routeProvider .when("/", { template: "123", resolve: { auth: function () { // do stuff } } }); } ]);
报错啦!!!上面的代码在启动阶段就会报下图所示的错误:
乍一看都不知道错在哪里,经过分析才知道,module.config 方法是在 on module loading,即模块加载过程中执行的,此时 $http 和 $q 等服务都还没有创建成功,不能当做依赖项注入到 module.config 方法中。
回到主题,AngularJS 框架的执行过程大致如下所示:
配合源码会理解的更清楚:
bindJQuery(); publishExternalAPI(angular); jqLite(document).ready(function() { angularInit(document, bootstrap); });
具体代码可以到源码中查看,这里简要说明一下:
bindJQuery() 尝试绑定jQuery对象,如果没有则采用内置的jqLite。
publishExternalAPI(angular) 初始化 angular 环境,为 angular 对象注册 module,forEach,extend 等方法。
关于 module 方法,在此要说明一下:
angular.module("myApp") 只传一个参数,为getter操作,返回 moduleInstance 对象,而 angular.module("myApp",[]) 传入两个参数,为setter操作,也返回 moduleInstance 对象
var moduleInstance = { // Private state _invokeQueue: invokeQueue, _runBlocks: runBlocks, requires: requires, name: name, provider: invokeLater("$provide", "provider"), factory: invokeLater("$provide", "factory"), service: invokeLater("$provide", "service"), value: invokeLater("$provide", "value"), constant: invokeLater("$provide", "constant", "unshift"), animation: invokeLater("$animateProvider", "register"), filter: invokeLater("$filterProvider", "register"), controller: invokeLater("$controllerProvider", "register"), directive: invokeLater("$compileProvider", "directive"), config: config, run: function(block) { runBlocks.push(block); return this; } }
angularInit(document, bootstrap) 方法内容如下:
function angularInit(element, bootstrap) { var elements = [element], appElement, module, names = ["ng:app", "ng-app", "x-ng-app", "data-ng-app"], NG_APP_CLASS_REGEXP = /sng[:-]app(:s*([wd_]+);?)?s/; function append(element) { element && elements.push(element); } forEach(names, function(name) { names[name] = true; append(document.getElementById(name)); name = name.replace(":", ":"); if (element.querySelectorAll) { forEach(element.querySelectorAll("." + name), append); forEach(element.querySelectorAll("." + name + ":"), append); forEach(element.querySelectorAll("[" + name + "]"), append); } }); forEach(elements, function(element) { if (!appElement) { var className = " " + element.className + " "; var match = NG_APP_CLASS_REGEXP.exec(className); if (match) { appElement = element; module = (match[2] || "").replace(/s+/g, ","); } else { forEach(element.attributes, function(attr) { if (!appElement && names[attr.name]) { appElement = element; module = attr.value; } }); } } }); if (appElement) { bootstrap(appElement, module ? [module] : []); } }
遍历names,通过 document.getElementById(name) 或者是 querySelectorAll(name) 检索到 element 后存入 elements 数组中,最后获取到 appElement 以及module。
举个例子:我们一般会在文档开始的html标签上写 ng-app="myApp",通过以上方法,我们最后可以得到名为 myApp 的 module,后调用 bootstrap(appElement,[module]);
bootstrap 中需要重点关注 doBootstrap 方法:
var doBootstrap = function() { element = jqLite(element); if (element.injector()) { var tag = (element[0] === document) ? "document" : startingTag(element); throw ngMinErr("btstrpd", "App Already Bootstrapped with this Element "{0}"", tag); } //通过上面分析我们知道此时 modules 暂时是这样的: modules = ["myApp"]; modules = modules || []; //添加$provide这个数组 modules.unshift(["$provide", function($provide) { $provide.value("$rootElement", element); }]); //添加 ng这个 module ,注意:1857行 我们注册过ng 这个module,并在1854行 我们注册过 它的依赖模块"ngLocale", //angularModule("ngLocale", []).provider("$locale", $LocaleProvider); 我们注册过ngLocale这个module modules.unshift("ng"); //调用createInjector(module) 此时:module为: //["ng",["$provide",function(){}],"myApp"] 两个type为string,一个为array var injector = createInjector(modules); injector.invoke(["$rootScope", "$rootElement", "$compile", "$injector", "$animate", function(scope, element, compile, injector, animate) { scope.$apply(function() { element.data("$injector", injector); compile(element)(scope); }); }] ); return injector; };
最后通过 $apply 将作用域转入 angular 作用域,所谓angular作用域是指:angular采用dirity-check方式进行检测,达到双向绑定。
再利用 compile 函数编译整个页面文档,识别出 directive,按照优先级排序,执行他们的 compilie 函数,最后返回 link function 的结合,通过 scope 与模板连接起来,形成一个即时,双向绑定。
至此,AngularJS 的执行过程也就告一段落了。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/81415.html
摘要:回调说白了,就是把函数当参数传给另一根函数,在另一个函数执行时调用此函数例如,在下面这段代码中,上面定义了两个函数和,下面的方法请求成功执行,失败执行异步异步的原理我看了网上的一些博客和例子,大都以定时任务为例子说明,但具体的原理我还是不太 回调 说白了,就是把函数当参数传给另一根函数,在另一个函数执行时调用此函数例如,在下面这段代码中,上面定义了两个函数success和error,下...
摘要:回调说白了,就是把函数当参数传给另一根函数,在另一个函数执行时调用此函数例如,在下面这段代码中,上面定义了两个函数和,下面的方法请求成功执行,失败执行异步异步的原理我看了网上的一些博客和例子,大都以定时任务为例子说明,但具体的原理我还是不太 回调 说白了,就是把函数当参数传给另一根函数,在另一个函数执行时调用此函数例如,在下面这段代码中,上面定义了两个函数success和error,下...
摘要:引言指令可以说是的核心,而其开发也是比较困难的,本文主要介绍指令的一些参数和的绑定策略。指令执行的优先级,用于多个指令同时作用于同一个元素时。改变父会影响指令,而改变指令不会影响父。在父和指令之间建立双向绑定。 引言 指令(Directive)可以说是 AngularJS 的核心,而其开发也是比较困难的,本文主要介绍指令的一些参数和scope的绑定策略。 参数 从 AngularJS ...
摘要:点击我啊当属性为空时,点击的时候页面不会刷新了,我们再也不需要这样写了点击我啊一般和指令结合使用点击我啊你点击我了一般和标签结合使用。使用了就就可以避免出现这种问题。如果链接中有表达式,就使用代替 a 点击我啊 当href属性为空时,点击的时候页面不会刷新了,我们再也不需要这样写了 点击我啊 一般和ng-click指令结合使用 #html 点击我啊 #scr...
摘要:自定义指令中有很多内置指令,一般都是以开头的比如等等。本文介绍的自定义指令的用法。该参数的意思是替换指令的内容,更改上面的例子。将属性绑定到父控制器的域中学习概念多指令中的参数中增加了的值和的点击函数。 自定义指令 angularjs中有很多内置指令,一般都是以ng开头的;比如:ng-app,ng-click,ng-repeat等等。本文介绍angularjs的自定义指令的用法。 指令...
阅读 1343·2021-09-26 09:55
阅读 1899·2019-08-30 12:45
阅读 1037·2019-08-29 11:20
阅读 3534·2019-08-26 11:33
阅读 3384·2019-08-26 10:55
阅读 1654·2019-08-23 17:54
阅读 2363·2019-08-23 15:55
阅读 2327·2019-08-23 14:23