【问题标题】:How can I use libraries included in <script> tags from a AngularJS Controller如何使用 AngularJS 控制器的 <script> 标签中包含的库
【发布时间】:2019-04-09 00:44:58
【问题描述】:

我正在尝试在我的控制器中使用 d3 库。根据我的研究,其中一种方法是创建一个指令来为脚本附加所需的属性。但我仍然无法获得我需要的 d3 库参考...

这是我的指令

angular.module('reportCtrl', [])

.directive('myCustomer', [function() {
    return {
        link: function(scope, element, attrs) {
            </script>
            angular.element('<script src="assets/lib/d3.js"></script>').append(element);
            angular.element('<script src="assets/lib/d3.promise.js"></script>').append(element);
        }
    }
}])

在我的控制器中,我使用 d3 引用。但我得到未定义的错误......我几乎需要等待这个脚本加载。但问题是 reportCtrl 在另一个“mainController”中,我似乎无法始终依赖应用程序的生命周期。

这是我的控制器...

.controller('reportController', function($scope, $http) {

    return $http.get('/api/admin/svc_spec_file_map')
    .success(dataset => {
        var container = d3.select('div.sheet').node();
}
});

【问题讨论】:

  • 那将永远无法工作。脚本在页面加载时执行,在控制器有机会运行并将脚本添加到 HTML 之前。您将需要实际手动执行以这种方式加载的任何脚本;查找“延迟加载”;应该有大量的文章和例子来说明如何做到这一点。

标签: javascript angularjs model-view-controller


【解决方案1】:

第一种方法:

index.html 文件中定义脚本src。您可以在 AngularJS 机制的脚本 src 之前执行此操作 - 模块、控制器等。

然后,您可以在后面的所有脚本中访问 D3 变量。

第二种方法:

如果 d3 库有 AngularJS 的扩展,您可以将其作为依赖模块注入。你最好检查一下。

第三种方法:

使用 webpack,您可以将 D3 直接/延迟加载到您需要的指令中,但使用动态导入:

import('path/to/d3').then(d3 => {
  // do something with d3.default()
})

关键点

你应该认为它是一个简单的 JS:如果你在启动 AngularJS 框架之前定义了 D3 变量,那么 D3 变量将在任何 AngularJS 应用程序中可用。

【讨论】:

    【解决方案2】:

    奇怪的是,您正在从指令中加载这些脚本,因为可以从 DOM 中添加和删除指令。

    从服务中加载它们会更明智:

    app.service('d3Loader', function($rootElement,$q) {
        var promise;
        this.load = function() {
            promise = promise || loadD3();
            return promise;
        };
        function loadD3 () {
            var defer = $q.defer();
            var d3url = "//unpkg.com/d3/dist/d3.js"; 
            var s = document.createElement("script");
            s.onload = function(ev) {
              defer.resolve(d3);
            };
            s.onerror = function(ev) {
              defer.reject(ev)
            };
            s.src=d3url;
            $rootElement[0].appendChild(s);
            return defer.promise;
        }
    })
    

    用法:

    d3Loader.load().then(function(d3) {
        console.log(d3);
    });
    

    DEMO on PLNKR

    【讨论】:

    • 谢谢,但它只对我有用一次。随后的执行 d3 仍然未定义 :( 不知道为什么。这是我的控制器 app.controller('reportController', function(d3Loader, $scope, $http) { d3Loader.load().then(function() { console.log(d3); }); })
    • 更新答案以创建$q 承诺并删除 jQuery 依赖项。
    猜你喜欢
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 2019-08-03
    • 2013-11-07
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 2020-02-04
    相关资源
    最近更新 更多