同一页面上的多个版本的脚本 (d3.js)

Posted

技术标签:

【中文标题】同一页面上的多个版本的脚本 (d3.js)【英文标题】:multiple versions of a script on the same page (d3.js) 【发布时间】:2013-04-15 21:44:37 【问题描述】:

我需要在同一页面上有多个版本的 javascript 库。除了手动重构一个版本以避免命名冲突之外,我该如何实现这一点?

有很多例子说明如何使用 Jquery (example) 做到这一点。然而,这似乎依赖于 jQuery 的优点。如何为任意脚本执行此操作?

更多细节:我正在使用d3.js,并且我正在插入其他人使用 d3 制作的可视化。问题是,其中一个可视化需要一个 d3 版本,另一个需要更新版本。这两个可视化应该在同一页面上可用 - 用户通过单击缩略图交换显示哪个可视化,然后使用 js 隐藏一个可视化并构建另一个可视化。因此,似乎也可以选择交换脚本而不是以无冲突的方式加载两者。

【问题讨论】:

【参考方案1】:

我遇到了和你类似的问题,一些可视化需要 d3 v3,而另一些需要 v4。 我就是这样实现的。

    在 index.html 中包含 d3 v3(因为我的大部分可视化都在 v3 上) 在 index.html 中包含 require.js 脚本 //你可以使用 cdn 路径 转到需要 v4 的 JavaScript。

    在顶部写下以下代码。

    function graphicviz(id)    
        require.config(
            paths: 
                d3: "https://d3js.org/d3.v4.min"
            
        );
    
        require(["d3"], function(d3) 
            //... D3 Code Here...
        );
    
    
    //Call The Function
    graphicviz(id); 
    

【讨论】:

【参考方案2】:

如果你看一下主要的 d3 源文件:https://github.com/mbostock/d3/blob/master/d3.js

你看它开始了:

d3 = function() 
  var d3 = 
    version: "3.1.5"
  ;
  //.....

所以 d3 只是一个对象。我不确定这是否是最好的方法,但我认为以下方法可行:

    包括一个版本的 d3 放行:d3versionX = d3; 包括下一个版本 与 2 相同,但版本号不同。 输入 d3 = d3versionX 其中 X 是页面加载时可视化的默认版本 在触发版本切换的缩略图上放置一个事件处理程序,并将 d3 变量设置为适当的版本号作为发生的第一件事。

用示例代码更新

有关工作示例,请参阅 this jsbin。相关代码:

  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
  <script>
    d3version4 = d3
    window.d3 = null
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
  <script>
    d3version3 = d3
    window.d3 = null
    // test it worked
    console.log('v3', d3version3.version)
    console.log('v4', d3version4.version)
  </script>

【讨论】:

这对我们有用。很抱歉延迟接受您的回答! 你能发布一个示例代码来说明你是如何让它工作的吗?我遇到了完全相同的问题,我想为页面上的两个不同图表使用两个不同版本的 D3.js。这个可以吗? 您好!我也很欣赏这里的一些示例代码。我有同样的问题,这似乎是最好的解决方法。【参考方案3】:

从 d3 版本 d3.v4 开始,脚本的标题看起来有点不同。您可以将标识符 global.d3 更改为 global.d3v4,使其看起来像这样

(function (global, factory) 
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (factory((global.d3v4 = global.d3v4 || )));
(this, (function (exports)  'use strict';

var version = "4.8.0";
...

现在您可以通过d3v4 调用d3 函数。

【讨论】:

【参考方案4】:

你需要使用这个一般原则

var x = 
    version: 1,
    alert1: function() 
        alert("1hi1");
    ,
    alert2: function() 
        alert("1hi2");
    
;

var y = x;

var x = 
    version: 2,
    alert1: function() 
        alert("2hi1");
    ,
    alert2: function() 
        alert("2hi2");
    
;

y.alert1();
x.alert1();

在jsfiddle

jquery 提供了它的noconflict 方法,许多库提供了相同的(不一定是名称)方法。但是您可以参考我的示例自行完成,具体取决于您正在加载的脚本的复杂程度。

这里是如何注入这2个不同的版本,并使用上述原理将它们分配给不同的变量。

<div id="version1"></div>
<div id="version2"></div>

var script1 = document.createElement("script"),
    script2 = document.createElement("script"),
    oldD3;

function noConflict() 
    oldD3 = d3;
    console.log("loaded old");
    script2.type = 'text/javascript';
    script2.src = "http://d3js.org/d3.v3.min.js";
    script2.addEventListener("load", ready, false);
    document.head.appendChild(script2);


function ready() 
    console.log("loaded new");
    console.log(d3, oldD3);
    document.getElementById("version1").textContent = oldD3.version;
    document.getElementById("version2").textContent = d3.version;


script1.type = 'text/javascript';
script1.src = "http://d3js.org/d3.v2.min.js";
script1.addEventListener("load", noConflict, false);
document.head.appendChild(script1);

在jsfiddle

【讨论】:

有没有办法创建 newD3 而不是 oldD3?

以上是关于同一页面上的多个版本的脚本 (d3.js)的主要内容,如果未能解决你的问题,请参考以下文章

同一页面上多个视频的交叉点观察者

同一页面上具有相同类别的多个光滑滑块?

ExtJs 同一页面上的两个或多个网格

同一页面上的多个 DataTables 具有不同的 ajax 源

同一页面上的多个 Jquery 滑动面板

同一页面上的多个 wmd 文本区域