【问题标题】:Why copy D3 source into an Angular Service?为什么要将 D3 源代码复制到 Angular 服务中?
【发布时间】:2014-04-21 11:59:52
【问题描述】:

ng-newsletter 的主要示例之一所述,我尝试将 d3 用于 Angular 项目。这显示了如何在 Angular 中设置 D3 服务。

我想知道将 D3 作为 Angular 服务如何与 Angular yeoman 和 bower 一起工作?还是我怀疑下面有冲突?

看来我需要该服务才能将 D3 服务注入到我的指令中。否则,当尝试通过脚本标记将 d3 库包含到全局空间中时,我的 Angular 指令无法引用 D3 对象。

我担心将 D3 用作 Angular 服务会降低代码的性能,这是通过使用 yeoman/grunt/bower 中的一些最佳实践获得的。例如缩小代码,使用 bower 更新到 D3 的未来版本。

【问题讨论】:

    标签: javascript angularjs svg d3.js


    【解决方案1】:

    我知道你的意思。如果您使用 bower,则 D3 会在全局范围内初始化。遵循 ng-newsletter 上描述的方法将为您提供 D3 实例作为服务,但您必须在 bower 之外对其进行管理。

    AngularJS 中服务的全部意义在于对象在需要时被初始化。因此,我选择的技术是一种妥协。它与 Yeoman Angular 生成器和凉亭一起使用,并将 D3 放入 Angular 服务中。然而,该服务实际上只是引用了 window.d3 对象,所以 AngularJS 纯粹主义者可能会认为它很 hacky。

    首先,用凉亭安装 D3:

    bower install d3 --save
    

    您的 bower.json 文件将更新为如下所示:

    {
      "name": "[YOUR_APP]",
      "version": "0.0.0",
      "dependencies": {
        "angular": "^1.3.0",
        "bootstrap-sass-official": "^3.2.0",
        "angular-animate": "^1.3.0",
        "angular-cookies": "^1.3.0",
        "angular-resource": "^1.3.0",
        "angular-route": "^1.3.0",
        "angular-sanitize": "^1.3.0",
        "angular-touch": "^1.3.0",
        "d3": "~3.5.5"
      },
      "devDependencies": {
        "angular-mocks": "^1.3.0"
      },
      "appPath": "app",
      "moduleName": "[YOUR_APP]"
    }
    

    请注意,D3 现在在那里 - "d3": "~3.5.5"。

    当您执行“grunt serve”以查看http://localhost:9000 上的站点时,D3 现在将包含在全局范围内。此外,当您执行“grunt build”时,它将与所有其他 javascript 一起被缩小和丑化并复制到 /dist 目录。

    到目前为止一切都很好,但它是在全局范围内,而不是在应该在的 AngularJS 服务中。

    编写服务很简单。在您的 app.js 中,添加以下内容:

    angular.module('d3Module', []).factory('d3', [
      function(){
    
        var d3;
        d3 = window.d3;
    
        // returning our service so it can be used
        return d3;
    }]);
    

    也许这不是返回 d3 的绝对最佳方式。也许应该按照本文底部的建议使用 module.exports 来完成 - http://lorenhoward.com/blog/simple-way-integrate-d3-angular/。我对 AngularJS 不是很熟悉,所以我可能遗漏了一些细微差别。

    无论如何,只需将“D3Module”添加到您应用的模块列表中即可:

    var app = angular
      .module('[YOUR_APP]', [
        'ngAnimate',
        'ngCookies',
        'ngResource',
        'ngRoute',
        'ngSanitize',
        'ngTouch',
        'd3Module'
      ])
      .config(function ($routeProvider) {
    
        // eg. Some rout stuff
    
      });
    

    现在可以将服务“d3”包含在指令中:

    app.directive('ngLogo', ['d3', function(d3) {
      return {
        restrict: 'A',
        scope: {},
        link: function(scope, element) {
    
        // Do some SVG stuff, eg:
        var svg = d3.select(element[0]).append('svg');
    
        }};
      }]);
    

    【讨论】:

    • 你在哪里包含了d3的javascript?如果我用凉亭得到 d3,它就没有任何 javascript。版本“d3”:“4.10.0”
    【解决方案2】:

    将 D3 注入服务不是必须的,它展示了我们如何使用 DI 来实现结果。如果您在 Angular 项目中使用 jQuery,您可以选择走相同的路线,或者只是将其添加到 index.html 中包含的脚本列表中。无论哪种方式都可以实现相同的结果 - jQuery 或 $ 就像 D3 一样成为全局的。

    【讨论】:

    • @sten0muchow。谢谢回复。我在将 D3 添加到全局空间并在我的角度指令中引用时遇到了麻烦。我的指令找不到 D3 对象。唔。现在我考虑一下,也许我需要引用为 window.d3?我会回去仔细检查一下。正如你所提到的,我认为它应该像你用 jQuery 解释的那样工作。无论哪种方式,遵循 DI 模式,将 3rd 方库复制或引用为 Angular 服务似乎都是一个不幸的选择。
    • 我返回并能够将 D3 引用为全局对象。但是我仍然想知道如果我使用 Angular Service/DI 方法是否有任何缺点我应该考虑。
    • 我假设你从 ng-newsletter 的人那里得到了关于 D3 指令的文章。这是我第一次听说这种方法的地方。如果没有,那么看看文章。 ng-newsletter.com/posts/d3-on-angular.html
    • 是的,我确实从 ng-newsletter 帖子开始。本教程让我开始质疑解决方案。
    猜你喜欢
    • 1970-01-01
    • 2017-04-20
    • 2016-03-19
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多