摘要:前言由于在博客系統的開發中和近期工作中的前端框架主要使用因此在這里記錄學習和使用的過程中遇到的一些需要記錄的點。執行過程弄清楚的執行過程是很重要的,這樣你才能在正確的時機做正確的事。至此,的執行過程也就告一段落了。
前言
由于在博客系統的開發中和近期工作中的前端框架主要使用 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 的執行過程也就告一段落了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/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的自定義指令的用法。 指令...
閱讀 1378·2021-09-26 09:55
閱讀 1917·2019-08-30 12:45
閱讀 1055·2019-08-29 11:20
閱讀 3555·2019-08-26 11:33
閱讀 3412·2019-08-26 10:55
閱讀 1685·2019-08-23 17:54
閱讀 2382·2019-08-23 15:55
閱讀 2341·2019-08-23 14:23