我正在学习Angular,我对我的应用程序的架构有一些疑问。
我将要开发的项目将使用大量的外部库:jQuery,jQuery.ui,jsPlumb等,不同的加载时间。
我知道与这些库相关的每个代码都必须在指令内处理。
我使用了有效使用Require JS的Backbone - 在每个视图中,我可以设置我需要的库,并且只要这些库可用就会加载视图。
现在,在角度方面 - 处理这个问题的正确方法是什么?
从我的头脑中,我在想:
将检查放在路由器内 - 检查是否加载了某条路线的所需库。
在每个指令中放置检查 - 例如,如果一个指令使用jsPlumb,在内部放置一个检查并在加载该库时返回指令内容 - 我相信这可能会在与其他指令交互时产生问题相同的视图,需要多个库加载时间不同。
仅在加载每个其他库后加载角度 - 这将导致加载时间过长。
处理所有这些问题的最佳方法是什么?
答案 0 :(得分:3)
您可以创建工厂来加载所需的外部库。加载后,为库的脚本返回一个延迟对象。这是我用于d3库的一个:
var d3js = angular.module('d3', []);
d3js.factory('d3Service', ['$document', '$q', '$rootScope', '$window',
function($document, $q, $rootScope, $window) {
var d = $q.defer();
function onScriptLoad() {
// Load client in the browser
$rootScope.$apply(function() { d.resolve($window.d3); });
}
// Create a script tag with d3 as the source
// and call our onScriptLoad callback when it
// has been loaded
var scriptTag = $document[0].createElement('script');
scriptTag.type = 'text/javascript';
scriptTag.async = true;
scriptTag.src = 'lib/d3.v3.js';
scriptTag.onreadystatechange = function () {
if (this.readyState == 'complete') onScriptLoad();
}
scriptTag.onload = onScriptLoad;
var s = $document[0].getElementsByTagName('body')[0];
s.appendChild(scriptTag);
return {
d3: function() { return d.promise; }
};
}]);
然后在你的指令中,使用延迟的then
函数等待它准备好
d3Service.d3().then(function(d3) {
// place code using d3 library here
}
如果您的指令需要访问多个库,则可以链接延迟。
d3Service.d3().then(function(d3) {
someOtherLibSvc.getLib().then(function(lib){
// place code using d3 library and someOtherLibrary here
}
}
为了避免这种链接检查bluebird
并使用Promise.join,Angular会自动带来$ q,所以我只是在这里使用它。
注意:如果你只是在angular之前加载JQuery,那么angular.element就已经引用了JQuery。因此,您不需要为JQuery执行此操作,只需在Angular之前将其加载到主html页面中
答案 1 :(得分:1)
简而言之 http://slides.com/thomasburleson/using-requirejs-with-angularjs#/
路由。
然而,现在不得不把定义和需要到处。对于大型应用程序,如果不仔细计划,这可能会变得混乱。使用grunt requirejs插件进行构建,因为没有这些东西就会被洗掉。
答案 2 :(得分:0)
我不确定这是执行此操作的“正确”方法,但这里可能是在Angular 1.x代码中处理外部库(在本例中为d3.js)的更简单方法。
这与@ aarosil的答案(使用工厂)基本相同,但对其他服务使用较少的依赖性 - 这是值得的。
var app = angular.module('SomeApp', []);
app.factory('LibraryFactory', function () {
var factory = {};
factory.getD3 = function(callback) {
if(!window.d3) {
var script = document.createElement("script");
script.src = "https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.9/d3.min.js";
document.head.appendChild(script);
script.onload = function() {
callback(window.d3);
};
} else {
callback(window.d3);
}
};
//factory.getSomeOtherLibrary = ...ditto
return factory;
});
使用工厂(例如,在控制器中):
app.controller('SomeTrialWithD3Ctrl', function ($scope, LibraryFactory) {
LibraryFactory.getD3(function main(d3) {
// place code using d3 library here
});
});
当然,如果您需要同时使用多个库,则可以链接回调。