gpt4 book ai didi

javascript - 将 D3 注入(inject) AngularJS 的正确约定

转载 作者:数据小太阳 更新时间:2023-10-29 04:45:49 26 4
gpt4 key购买 nike

我见过只使用全局 D3 对象的指令,我也见过通过在服务中返回它来注入(inject)全局 D3 对象的指令,我见过添加 D3 脚本并返回一个在提供 D3 对象的脚本加载时解决的 promise 。

在可注入(inject)服务中使用它似乎最有意义(参见示例 1 和 2),但我不确定哪种方式更好。示例 2 将保证 D3 在运行任何代码之前已经加载,但似乎没有人这样做,而且这意味着您必须将整个指令包装在服务中,否则 d3 和创建的 svg 对象超出范围或可能未定义(参见示例 2),但我相信至少编译的 promise 总是首先解决,参见示例 3。

示例 1:服务传递 D3 全局对象

.factory('D3Service', [,
function () {

// Declare locals or other D3.js
// specific configurations here.

return d3;
}]);

示例 2:服务将 D3 脚本添加到 DOM 并传递 promise

.factory('D3Service', ['$window', '$document', '$q', '$rootScope',
function ($window, $document, $q, $rootScope) {

var defer = $q.defer();

var scriptTag = $document[0].createElement('script');
scriptTag.type = 'text/javascript';
scriptTag.src = 'https://d3js.org/d3.v3.min.js';
scriptTag.async = true;
scriptTag.onreadystatechange = function () {

if (this.readyState == 'complete') {
onScriptLoad();
}
}
scriptTag.onload = onScriptLoad;

var script = $document[0].getElementsByTagName('body')[0];
script.appendChild(scriptTag);

//---
// PUBLIC API
//---

return {
d3: function () {
return defer.promise;
}
};

//---
// PRIVATE METHODS.
//---

// Load D3 in the browser
function onScriptLoad () {
$rootScope.$apply(function () {
defer.resolve($window.d3);
});
}
}]);

示例 3:使用编译添加 SVG 并不意味着 SVG 在链接中可用,但至少编译的 promise 总是首先解决

        // Perform DOM and template manipulations
function compile ($element, $attrs, $transclude) {

var svg;

// Callback provides raw D3 object
D3Service.d3().then(function (d3) {

// Create a responsive SVG root element
svg = d3.select($element[0])
.append('svg')
.style('width', '100%');
});

// Return the link function
return function($scope, $element, $attrs) {

// Is svg undefined?

// Maybe? so have to wrap everything again in service
D3Service.d3().then(function (d3) {

function render() {
// d3 and svg guaranteed to be available, but code gets really ugly looking and untestable
}
});

function render() {
// d3 and svg have to be passed in as they may not be available, but code is cleaner
}
};
}

最佳答案

在遇到d3Angular 的问题时,我也有过类似的疑问。似乎有几种方法可以解决这个问题;每个都是可行的,但没有一个感觉流畅或自然。就其核心而言,d3Angular 似乎是两种截然不同的技术,而且它们开箱即用地不能很好地协同工作。别误会我的意思,他们在一起工作非常棒,但他们需要互相热身。因此充其量,我们可以在 Angular 框架内为 d3 提供一个 Playground 。我相信这个 Playground 应该是一个指令

但是关于返回 promise 的模块化 d3Service 方法(根据 d3.js 文件的加载):

angular.module('myApp.directives', ['d3'])
.directive('barChart', ['d3Service', function(d3Service) {
return {
link: function(scope, element, attrs) {
d3Service.d3().then(function(d3) {
// d3 is the raw d3 object
});
}}
}]);

虽然这在 ngNewsletter 中非常详细,使用将 script 标记直接写入 DOM 的服务似乎有点过分,因为它可以与所有其他 javascript 文件一起包含在 index.html 中。我的意思是,我们有一个我们知道使用此文件的 指令 ,那么为什么不直接加载它呢?看起来不需要跳过障碍,只是:

<script src="/js/third-party/d3js/d3.min.js"></script>

但是,这种方法 promise 确实提供了模块化——假设我们正在构建多个应用程序并且每个应用程序都需要 d3,那么是的,能够非常容易地注入(inject)我们的 d3应用程序级别的模块很棒。但是,您总是需要等待那个 promise ,即使我们知道它会在初始加载后立即解决,您仍然需要解决它。在使用它的任何指令或 Controller 中。总是。真可惜。

正如我所说,我选择只在我的 index.html 中包含 d3.js,这样我就可以在我的指令中访问它而无需解决一个 promise 。这可能是平行的:FWIW,我使用 JQuery promises 而不是 Angular promises,那么当我需要 JQuery 时我该怎么做?好吧,我只是在需要时调用它 ($.Deferred()),我的意思是,以类似的方式调用 d3 似乎并没有那么令人震惊我。

虽然我确实使用了 d3Service,但它更多的是用于帮助函数而不是其他任何东西。例如,当我想获得一个 SVG 来做工作时,为什么不调用一个函数来给我一个响应式 SVG:

指令(链接)

var svg = d3Service.getResponsiveCanvas(scope.id, margin, height, width);

服务

app.service('d3Service', function() {

return {
getResponsiveCanvas: function(id, margin, height, width) {
return d3.select('#' + id)
.append('div')
.classed('svg-container', true)
.append('svg')
.attr('id', 'svg-' + id)
.attr('preserveAspectRatio', 'xMinYMin meet')
.attr('viewBox', '0 0 ' + (width + margin.left + margin.right) + ' ' + (height + margin.top + margin.bottom))
.classed('svg-content-responsive', true)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
}
}
});

我有类似的功能可以将轴添加到 SVG。这确实有代码的味道,但同样,由于 d3 的本质,我们直接操作 DOM,所以我的经验是无论我们把它放在哪里,它都会变得丑陋而且感觉不太好Angular-like,所以你不妨制作一些让你的生活更轻松的服务。

关于javascript - 将 D3 注入(inject) AngularJS 的正确约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34010378/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com