簡體   English   中英

相對於.js文件的Angular指令templateUrl

[英]Angular directive templateUrl relative to .js file

我正在建立一個角度指令,將在幾個不同的位置使用。 我不能總是保證使用該指令的應用程序的文件結構,但我可以強制用戶將directive.jsdirective.html (不是真正的文件名)放在同一個文件夾中。

當頁面評估directive.js ,它認為templateUrl是相對於它自己的。 是否可以將templateUrl設置為相對於directive.js文件?

或者建議只在模板中包含模板。

我想我可能想根據不同的情況加載不同的模板,所以寧願能夠使用相對路徑而不是更新directive.js

當前正在執行的腳本文件將始終是scripts數組中的最后一個,因此您可以輕松找到其路徑:

// 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;
    })()
);

正如您所說,您希望在指令的不同時間提供不同的模板,為什么不允許模板本身作為屬性傳遞給指令?

<div my-directive my-template="template"></div>

然后在指令中使用類似$compile(template)(scope)東西。

此代碼位於名為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);

我的測試基於以下關於使用require來延遲加載角度的博客: http//ify.io/lazy-loading-in-angularjs/

require.js會產生一個requireConfig引導程序

requireConfig會產生一個有角度的app.js

angular app.js會產生我的routes.js

我有一個由revel web框架和asp.net mvc提供的相同代碼。 在revel document.getElementsByTagName(“script”)中生成了一個指向我的require bootstrap js文件而不是我的routes.js的路徑。 在ASP.NET MVC中,它生成了Visual Studio注入的Browser Link腳本元素的路徑,該腳本元素在調試會話期間放在那里。

這是我的工作路線.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,有時您需要動態生成它。 您的情況選擇。

除了Alon Gubkin的答案之外,我建議使用Immediately-Invoked Function Expression定義一個常量來存儲腳本的路徑並將其注入到指令中:

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'
    }
});

有些人可能會認為它有點“hacky”,但我認為只有一種方法可以做到這一點,任何東西都會變成黑客。
我也有很多運氣也這樣做:

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;
    } 
  });

然后在應用程序中包含模塊后在應用程序中使用代碼。
在app配置功能中:

.config(['$routeProvider', '$appUrlProvider', function ($routeProvider, $appUrlProvider) {

    $routeProvider
        .when('/path:folder_path*', {
            controller: 'BrowseFolderCntrl',
            templateUrl: $appUrlProvider.route('views/browse-folder.html')
        });
}]);

在app控制器中(如果需要):

var MyCntrl = function ($scope, $appUrl) {
    $scope.templateUrl = $appUrl('views/my-angular-view.html');
};

它會創建一個新的javascript錯誤並拉出堆棧跟蹤。 然后解析出所有URL(不包括調用行/ char號)。
然后,您可以拉出數組中的第一個,該數組將是運行代碼的當前文件。

如果你想集中代碼然后拉出數組中的第二個( [1] )來獲取調用文件位置,這也很有用。

正如一些用戶指出的那樣,相關路徑在構建靜態文件時沒有用處,我強烈建議這樣做。

Angular中有一個名為$ templateCache的漂亮功能,它或多或少地緩存模板文件,下次該角度需要一個,而不是發出實際請求,它提供緩存版本。 這是使用它的典型方法:

module = angular.module('myModule');
module.run(['$templateCache', function($templateCache) {
$templateCache.put('as/specified/in/templateurl/file.html',
    '<div>blabla</div>');
}]);
})();

因此,通過這種方式,您既可以解決相對網址的問題,也可以獲得性能。

當然我們喜歡使用單獨的模板html文件(與反應相反)的想法,所以上面的內容並不好。 這是構建系統,它可以讀取所有模板html文件並構造如上所述的js。

grunt,gulp,webpack有幾個html2js模塊,這是它們背后的主要思想。 我個人經常使用gulp ,所以我特別喜歡gulp-ng-html2js,因為它非常容易。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM