我试图延迟加载组件。该组件是一个带有嵌入式脚本标记的html片段,其中包含控制器。
<script>
... controller code .....
</script>
<div>
... template ....
</div>
片段是在一个html请求中生成的,所以我不能在状态定义中使用templateUrl AND componentURL。
我尝试使用templateProvider来获取组件,而不是提取函数的脚本代码并使用对controllerProvider的引用来注册它。
我确信必须有一个更好的方法来做到这一点,而不是我提出的丑陋的解决方案。我对controllerpovider进行了全局引用,然后使用getComponent服务通过templateProvide读取组件。接下来,我提取脚本并对其进行评估,并注册控制器。
请参阅plunker了解我尝试解决此问题的方法。
.factory('getComponent', function($http, $q) {
return function (params) {
var d = $q.defer();
// optional parameters
$http.get('myComponent.html').then(function (html) {
// the component contains a script tag and the rest of the template.
// the script tags contain the controller code.
// first i extract the two parts
var parser = new window.DOMParser();
var doc = parser.parseFromString(html.data, 'text/html');
var script = doc.querySelector('script');
// Here is my problem. I now need to instantiate and register the controller.
// It is now done using an eval which of cours is not the way to go
eval(script.textContent);
// return the htm which contains the template
var html = doc.querySelector('body').innerHTML;
d.resolve(html);
});
return d.promise;
};
})
也许可以使用templateProvider和controllerProvider来完成,但我不确定如何使用一个http请求解决这两个问题。任何帮助/想法将不胜感激。
答案 0 :(得分:1)
{ controller: function() {} }
在州定义中完全有效ng-controller
。这是我如何一起攻击这个。 getController
工厂现在保留了“组件承诺”的缓存。我保留了你的eval和模板解析,将响应分成两部分。我用包含ctrl / template的对象解决了promise。
.factory('getComponent', function($http, $q) {
var components = {};
return function (name, params) {
if (components[name])
return components[name];
return components[name] = $http.get(name + '.html').then(extractComponent);
function extractComponent(html) {
var parser = new window.DOMParser();
var doc = parser.parseFromString(html.data, 'text/html');
var script = doc.querySelector('script');
// returns a function from the <script> tag
var ctrl = eval(script.textContent);
// return the htm which contains the template
var tpl = doc.querySelector('body').innerHTML;
// resolve the promise with this "component"
return {ctrl: ctrl, tpl: tpl};
}
};
})
<script>
var controller = function($scope) {
$scope.sayHi = function() {
alert(' Hi from My controller')
}
};
// This statement is assigned to a variable after the eval()
controller;
</script>
// No ng-controller
<div>
Lazyloaded template with controller in one pass.
<button ng-click="sayHi()">Click me to see that the controller actually works.</button>
</div>
在州定义中:
getComponent
工厂获取名为'myComponent'的组件(提示:'myComponent'可能是路由参数)component
,并将控制器/模板返回到UI-Router。我应该提一下,在一个html文件中获取一个控制器和模板,并手动解析我的气味。
您可以追求的一些变化: