AngularJS: использование сторонних библиотек без отображения глобальной переменной
Каков наилучший способ использования сторонней библиотеки в Angular без раскрытия глобальной переменной?
Например, если я использовал underscore.js, я хочу вставлять _ только в те контроллеры, которые его используют.
angular.module('module').controller(function(_) {
// _ is injected only into this scope
};
Чтобы получить этот эффект, я видел, как некоторые люди загружают ярлык во всем мире с тегом script, а затем создают такой сервис:
myModule.factory('_', function ($window) {
return $window._;
});
Однако это все еще загрязняет глобальную область видимости с помощью _.
Есть ли способ Angular регистрировать и вставлять сторонние библиотеки, не вызывая этой проблемы?
Ответы
Ответ 1
Вы ничего не можете сделать о том, как записываются библиотеки сторонних разработчиков, за исключением того, что они разворачивают их и создают вашу собственную версию.
Сторонние библиотеки почти всегда создают такие переменные в глобальной области, и вы упомянете два наиболее часто используемых способа их использования в модуле Angular: путем ввода $window
и использования их напрямую или путем создания тонкий service
, который обеспечивает объект.
Я бы предпочел последнее в большинстве случаев, потому что он упрощает код в других модулях. Кроме того, на мой взгляд, сервисный подход делает код в ваших контроллерах менее "волшебным" и более отлаживаемым, так как становится ясно, где библиотека, например. _
. Переменные, появляющиеся "из воздуха", представляют собой проблему с глобальными переменными.
Библиотека по-прежнему будет "загрязнять" глобальную область видимости, если вы явно не удаляете их из глобальной области видимости, возможно, после получения указателя на них в службе, которая затем может передать ее. Однако я не вижу никакой мотивации для этого. Любые другие попытки, такие как использование службы Angular для фактической загрузки третьей стороны script и ее оценки, каким-то образом препятствующим ее достижению глобальной области, кажутся весьма неэффективными, чрезмерно спроектированными и медленными (как в вычислительной, так и в отношении когда HTTP-запросы запущены).
В противном случае хорошая идея не создавать глобальные переменные, нежели строго необходимые.
Ответ 2
Для сторонних библиотек, поддерживающих функцию noConflict
, например Underscore и jQuery - вы можете использовать это для предотвращения глобального загрязнения в Angular factory.
myModule.factory('_', ['$window', function ($window) {
var underscore = $window._.noConflict();
return underscore;
}]);
Поскольку все службы в Angular являются одноточечными, это означает, что инжектор использует каждый рецепт не более одного раза для создания объекта. Затем инжектор кэширует ссылку для всех будущих потребностей.
Ответ 3
Майка прав, вы не можете "остановить" модуль от неприятностей. Как только что-то вызывает window.whatever =...
Require.js, хотя и классный, как библиотека/методология определения асинхронного модуля, которая помогает людям, которые создают пакеты, делать это, не опускаясь в глобальное пространство имен. Это не поможет преступникам, но это аккуратно.
http://requirejs.org/
Ответ 4
Поместите сторонние библиотеки в константы angular.
Сохраняет ваш код читаемым и чистым, и вы можете вводить их в определенные контроллеры, директивы,... где вы хотите их использовать.
angular
.module('sampleApp', [])
.constant('_', window._)
.constant('$', window.$)
Ответ 5
Я создал инструмент, который создаст angular factory, а не глобальный для всех библиотек, которые поддерживают js. Поскольку большинство библиотек поддерживают require.js, я смог написать функцию, которая имитирует, требует функции "define", но вместо добавления требуемой библиотеки она добавляет ее как angular для инъекций. Это практически plug n' play
. Просто включите источник js после jQuery и angular, и вам хорошо идти. Он назвал глобальный инжектор angular и доступен на github. Здесь ссылка: https://github.com/btesser/angular-global-injector