从 jsdom 迁移到 phantomJS ? (基本 DOM 创建)

Migrate from jsdom to phantomJS ? (basic DOM creation)

米。 Bostock 指出 nodejs 的 jsdom 对 svg 的支持不完整,而且对我来说很关键,不支持 getBBox()。此外,他建议切换到 nodejs 的 PhantomJS。我检查了一下,但这种方法对我来说是新的。

我的 nodejs + jsdom 脚本创建了一个虚拟 DOM,我的 d3js 使用它播放,如下所示:

var jsdom = require('jsdom');
jsdom.env(                             // creates virtual page
  "<html><body></body></html>",        // create my DOM hook,
  [ 'http://d3js.org/d3.v3.min.js',    // add my online dependencies ...
  '../js/d3.v3.min.js',                // ... & local ones
  '../js/jquery-2.1.3.min.js'],

  function (err, window) {
           //my normal JS or nodejs code here !
  }
);

如何将这个nodejs + jsdom迁移到nodejs + PhantomJS?

既然你想从 node.js 做这个,你应该使用像 phantomjs-node 这样的 PhantomJS 桥(phantom npm 模块)。

当你不在 PhantomJS 中打开一个页面时,你实际上是在一个 about:blank 页面中工作,你需要添加 '--local-to-remote-url-access =yes' 底层 PhantomJS 进程的命令行选项,以便可以加载远程资源。也许 --web-security=false--ssl-protocol=anyignore-ssl-errors=true 可能是必要的。

要将其他脚本注入 DOM,您需要使用 injectJs() for local files and includeJs() for remote files. Furthermore, you cannot directly access the DOM in PhantomJS, because it has two contexts. The sandboxed page context (page.evaluate()) 无法访问外部定义的变量,因此如果需要,您需要将它们显式传入。

var phantom = require('phantom');
var async = require('async');

function run(page, ph) {
    page.evaluate(function () {
        // page context: DOM code here
        return document.title;
    }, function (title) {
        // node code here
        console.log('Page title is ' + title);
        ph.exit();
    });
}

var remoteScripts = [ "http://d3js.org/d3.v3.min.js" ];
var localScripts = [ "../js/d3.v3.min.js", "../js/jquery-2.1.3.min.js" ];
phantom.create('--local-to-remote-url-access=yes', '--web-security=false', function (ph) {
    ph.createPage(function (page) {
        async.series(remoteScripts.map(function(url){
            return function(next){
                page.includeJs(url, function(){
                    next();
                });
            };
        }), function(){
            async.series(localScripts.map(function(url){
                return function(next){
                    page.injectJs(url, function(){
                        next();
                    });
                };
            }), function(){
                run(page, ph);
            });
        });
    });
});

您可以使用 async 将脚本列表加载到 DOM。我使用了 series() 函数。