This repository has been archived by the owner on Jun 22, 2020. It is now read-only.
/
ui-router-require-polyfill.js
153 lines (117 loc) · 4.69 KB
/
ui-router-require-polyfill.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
* @author Kuitos
* @homepage https://github.com/kuitos/
* @since 2015-12-11
* 基于ui-router & script-loader实现的按需加载方案,可在不修改一行js代码的情况下实现angular框架的按需加载
* 依赖于 browser-script-loader (https://github.com/kuitos/script-loader)
*/
;(function (angular, undefined) {
'use strict';
angular
.module('ui.router.requirePolyfill', ['ng', 'ui.router', 'oc.lazyLoad'])
.decorator('uiViewDirective', DecoratorConstructor)
.config(config);
config.$inject = ['$ocLazyLoadProvider'];
function config($ocLazyLoadProvider) {
$ocLazyLoadProvider.config({debug: true});
}
/**
* 装饰uiView指令,给其加入按需加载的能力
*/
DecoratorConstructor.$inject = ['$delegate', '$log', '$q', '$compile', '$controller', '$interpolate', '$state', '$ocLazyLoad'];
function DecoratorConstructor($delegate, $log, $q, $compile, $controller, $interpolate, $state, $ocLazyLoad) {
// 移除原始指令逻辑
$delegate.pop();
// 在原始ui-router的模版加载逻辑中加入脚本请求代码,实现按需加载需求
$delegate.push({
restrict: 'ECA',
priority: -400,
compile : function (tElement) {
var initial = tElement.html();
return function (scope, $element, attrs) {
var current = $state.$current,
name = getUiViewName(scope, attrs, $element, $interpolate),
locals = current && current.locals[name];
if (!locals) {
return;
}
$element.data('$uiView', {name: name, state: locals.$$state});
var template = locals.$template ? locals.$template : initial,
processResult = processTpl(template);
var compileTemplate = function () {
$element.html(processResult.tpl);
var link = $compile($element.contents());
if (locals.$$controller) {
locals.$scope = scope;
locals.$element = $element;
var controller = $controller(locals.$$controller, locals);
if (locals.$$controllerAs) {
scope[locals.$$controllerAs] = controller;
}
$element.data('$ngControllerController', controller);
$element.children().data('$ngControllerController', controller);
}
link(scope);
};
// 模版中不含脚本则直接编译,否则在获取完脚本之后再做编译
if (processResult.scripts.length) {
loadScripts(processResult.scripts).then(compileTemplate);
} else {
compileTemplate();
}
};
}
});
return $delegate;
/**
* Shared ui-view code for both directives:
* Given scope, element, and its attributes, return the view's name
*/
function getUiViewName(scope, attrs, element, $interpolate) {
var name = $interpolate(attrs.uiView || attrs.name || '')(scope);
var inherited = element.inheritedData('$uiView');
return name.indexOf('@') >= 0 ? name : (name + '@' + (inherited ? inherited.state.name : ''));
}
/**
* 从模版中解析出script外链脚本
* @return tpl:处理后的模版字符串 scripts:提取出来的脚本链接,数组索引对应脚本优先级, 数据结构: [['a.js','b.js'], ['c.js']]
*/
function processTpl(tpl) {
var SCRIPT_TAG_REGEX = /<script\s+((?!type=('|")text\/ng-template('|")).)*>.*<\/script>/gi,
SCRIPT_SRC_REGEX = /.*\ssrc="(\S+)".*/,
SCRIPT_SEQ_REGEX = /.*\sseq="(\S+)".*/,
scripts = [];
// 处理模版,将script抽取出来
tpl = tpl.replace(SCRIPT_TAG_REGEX, function (match) {
// 抽取src部分按设置的优先级存入数组,默认优先级为0(最高优先级)
var matchedScriptSeq = match.match(SCRIPT_SEQ_REGEX),
matchedScriptSrc = match.match(SCRIPT_SRC_REGEX);
var seq = (matchedScriptSeq && matchedScriptSeq[1]) || 0;
scripts[seq] = scripts[seq] || [];
if (matchedScriptSrc && matchedScriptSrc[1]) {
scripts[seq].push(matchedScriptSrc[1]);
}
return '<!-- script replaced -->';
});
return {
tpl : tpl,
scripts: scripts.filter(function (script) {
// 过滤空的索引
return !!script;
})
};
}
// 按脚本优先级加载脚本
function loadScripts(scripts) {
var promise = $ocLazyLoad.load(scripts.shift()),
nextGroup;
while (scripts.length) {
nextGroup = scripts.shift();
promise = promise.then(function () {
return $ocLazyLoad.load(nextGroup);
});
}
return promise;
}
}
})(window.angular);