Я создаю директиву angular, которая будет использоваться в нескольких разных местах. Я не всегда могу гарантировать файловую структуру приложения, в котором используется директива, но я могу заставить пользователя поместить directive.js
и directive.html
(а не настоящие имена файлов) в одну и ту же папку.
Когда страница оценивает объект directive.js
, он считает, что он относится templateUrl
к самой себе. Можно ли установить templateUrl
относительное значение directive.js
файла?
Или рекомендуется просто включить шаблон в саму директиву.
Я думаю, что могу захотеть загрузить разные шаблоны в зависимости от разных обстоятельств, поэтому предпочел бы иметь возможность использовать относительный путь, а не обновлять directive.js
javascript
angularjs
path
педальпет
источник
источник
Ответы:
Текущий исполняемый файл сценария всегда будет последним в массиве сценариев, поэтому вы можете легко найти его путь:
// directive.js var scripts = document.getElementsByTagName("script") var currentScriptPath = scripts[scripts.length-1].src; angular.module('app', []) .directive('test', function () { return { templateUrl: currentScriptPath.replace('directive.js', 'directive.html') }; });
Если вы не знаете, как называется имя сценария (например, если вы упаковываете несколько сценариев в один), используйте следующее:
return { templateUrl: currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1) + 'directive.html' };
Примечание . В случаях, когда используется замыкание, ваш код должен находиться снаружи, чтобы гарантировать, что currentScript вычисляется в правильное время, например:
// directive.js (function(currentScriptPath){ angular.module('app', []) .directive('test', function () { return { templateUrl: currentScriptPath.replace('directive.js', 'directive.html') }; }); })( (function () { var scripts = document.getElementsByTagName("script"); var currentScriptPath = scripts[scripts.length - 1].src; return currentScriptPath; })() );
источник
<script>
тег, он немедленно выполняет его, прежде чем продолжить отображение страницы, поэтому в глобальной области сценария последний<script>
тег всегда является последним.path = currentScriptPath.split("/"); path.pop(); path.push("directive.html");
Это не имеет никаких зависимостей от имен файлов и поддерживает «directive.js», «/directive.js» и «path / to / directive.js». Кодекс соревнований по гольфу состоит в том, чтобы объединить их в одно заявление (с использованием splice и др.)Как вы сказали, вы хотите предоставлять директивам разные шаблоны в разное время, почему бы не разрешить передачу самого шаблона в директиву в качестве атрибута?
<div my-directive my-template="template"></div>
Затем используйте что-то вроде
$compile(template)(scope)
внутри директивы.источник
$compile
метод на любой переданный шаблон? Возможно, мне$compile
все равно придется использовать , так что это может быть хорошим предложением.В дополнение к ответу Алона Губкина я бы предложил определить константу, используя выражение немедленного вызова функции, чтобы сохранить путь к сценарию и вставить его в директиву:
angular.module('app', []) .constant('SCRIPT_URL', (function () { var scripts = document.getElementsByTagName("script"); var scriptPath = scripts[scripts.length - 1].src; return scriptPath.substring(0, scriptPath.lastIndexOf('/') + 1) })()) .directive('test', function(SCRIPT_URL) { return { restrict : 'A', templateUrl : SCRIPT_URL + 'directive.html' } });
источник
Этот код находится в файле routes.js
У меня не сработало следующее:
var scripts = document.getElementsByTagName("script") var currentScriptPath = scripts[scripts.length-1].src; var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);
сделали следующее:
var bu2 = document.querySelector("script[src$='routes.js']"); currentScriptPath = bu2.src; baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);
Мой тест основан на следующем блоге об использовании ленивой загрузки angular: http://ify.io/lazy-loading-in-angularjs/
require.js порождает загрузочную программу requireConfig
requireConfig порождает угловой app.js
angular app.js порождает мои routes.js
У меня был тот же код, который обслуживается веб-фреймворком revel и asp.net mvc. В revel document.getElementsByTagName ("script") создается путь к моему js-файлу require bootstrap, а НЕ к моему routes.js. в ASP.NET MVC он создает путь к внедренному в Visual Studio элементу сценария Browser Link, который помещается туда во время сеансов отладки.
это мой рабочий код routes.js:
define([], function() { var scripts = document.getElementsByTagName("script"); var currentScriptPath = scripts[scripts.length-1].src; console.log("currentScriptPath:"+currentScriptPath); var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); var bu2 = document.querySelector("script[src$='routes.js']"); currentScriptPath = bu2.src; console.log("bu2:"+bu2); console.log("src:"+bu2.src); baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); return { defaultRoutePath: '/', routes: { '/': { templateUrl: baseUrl + 'views/home.html', dependencies: [ 'controllers/HomeViewController', 'directives/app-style' ] }, '/about/:person': { templateUrl: baseUrl + 'views/about.html', dependencies: [ 'controllers/AboutViewController', 'directives/app-color' ] }, '/contact': { templateUrl: baseUrl + 'views/contact.html', dependencies: [ 'controllers/ContactViewController', 'directives/app-color', 'directives/app-style' ] } } }; });
Это мой вывод на консоль при запуске из Revel.
currentScriptPath:http://localhost:9000/public/ngApps/1/requireBootstrap.js routes.js:8 baseUrl:http://localhost:9000/public/ngApps/1/ routes.js:10 bu2:[object HTMLScriptElement] routes.js:13 src:http://localhost:9000/public/ngApps/1/routes.js routes.js:14 baseUrl:http://localhost:9000/public/ngApps/1/
Еще одна приятная вещь, которую я сделал, - это воспользоваться конфигурацией require и добавить в нее несколько пользовательских конфигураций. т.е. добавить
customConfig: { baseRouteUrl: '/AngularLazyBaseLine/Home/Content' }
затем вы можете получить его, используя следующий код из routes.js
var requireConfig = requirejs.s.contexts._.config; console.log('requireConfig.customConfig.baseRouteUrl:' + requireConfig.customConfig.baseRouteUrl);
иногда вам нужно заранее определить baseurl, иногда вам нужно динамически его генерировать. Ваш выбор для вашей ситуации.
источник
Кто-то может посоветовать это слегка «взломать», но я думаю, что пока не будет только один способ сделать это, все будет взломано.
Мне очень повезло с этим:
angular.module('ui.bootstrap', []) .provider('$appUrl', function(){ this.route = function(url){ var stack = new Error('dummy').stack.match(new RegExp(/(http(s)*\:\/\/)[^\:]+/igm)); var app_path = stack[1]; app_path = app_path.slice(0, app_path.lastIndexOf('App/') + 'App/'.length); return app_path + url; } this.$get = function(){ return this.route; } });
Затем при использовании кода в приложении после включения модуля в приложение.
В функции конфигурации приложения:
.config(['$routeProvider', '$appUrlProvider', function ($routeProvider, $appUrlProvider) { $routeProvider .when('/path:folder_path*', { controller: 'BrowseFolderCntrl', templateUrl: $appUrlProvider.route('views/browse-folder.html') }); }]);
И в контроллере приложения (если требуется):
var MyCntrl = function ($scope, $appUrl) { $scope.templateUrl = $appUrl('views/my-angular-view.html'); };
Он создает новую ошибку javascript и извлекает трассировку стека. Затем он анализирует все URL-адреса (за исключением номера вызывающей строки / символа).
Затем вы можете просто вытащить первый в массиве, который будет текущим файлом, в котором выполняется код.
Это также полезно, если вы хотите централизовать код, а затем вытащить второй (
[1]
) в массиве, чтобы получить местоположение вызывающего файла.источник
Как указали несколько пользователей, соответствующие пути не помогают при создании статических файлов, и я настоятельно рекомендую это сделать.
В Angular есть отличная функция под названием $ templateCache , которая более или менее кэширует файлы шаблонов, и в следующий раз, когда Angular потребует один, вместо фактического запроса он предоставит кешированную версию. Это типичный способ его использования:
module = angular.module('myModule'); module.run(['$templateCache', function($templateCache) { $templateCache.put('as/specified/in/templateurl/file.html', '<div>blabla</div>'); }]); })();
Таким образом, вы оба решаете проблему относительных URL-адресов и повышаете производительность.
Конечно, нам нравится идея иметь отдельные html-файлы шаблонов (в отличие от реакции), так что приведенное выше само по себе бесполезно. А вот и система сборки, которая может читать все html-файлы шаблонов и создавать js-файлы, подобные приведенному выше.
Есть несколько модулей html2js для grunt, gulp, webpack, и это их основная идея. Лично я часто использую gulp , поэтому мне особенно нравится gulp-ng-html2js, потому что он делает именно это очень легко.
источник