如何在一页上有效地拥有多个只读的摩纳哥差异视图?

How to efficiently have many readonly Monaco Diff Views on one page?

我的理解是,Monaco 针对编辑进行了优化,一次显示一个文件,具有固定大小的编辑器,它有自己的滚动条。

相反,我试图构建一个页面,其中多个文件的差异在彼此下方

我意识到这与摩纳哥的初衷大相径庭,但最终似乎会应用相同的视口和虚拟渲染技巧,所以也许这在某种程度上是可能的?

我尝试为每个文件创建一个 Monaco 实例,但在大约 30 个实例时开始变得非常缓慢。

一个非常丑陋的解决方法可能是拥有一个 Monaco 实例,连接所有文件,然后使用 ViewZones、自定义行号提供程序和代码折叠提供程序来实现多个文件的效果。这听起来是不是很疯狂,或者真的有用吗?

还有其他建议吗?为什么 IStandaloneDiffEditor 的名称中有 standalone?这是否意味着还有另一种方法可以更高效地创建许多差异编辑器?

Citate from your question: I tried creating one Monaco instance per file, but that starts getting really sluggish around 30 instances.

您的问题的解决方案

正如您提到的那样,性能不佳。这是因为您的服务器或可能是您的客户端没有足够的内存。您必须向服务器添加更多内存,或者可能向客户端添加更多内存以获得更多性能。因为我没有足够的信息我不能说它是服务器还是客户端。但是这种方法效率不高。

Citate from your question: Why does IStandaloneDiffEditor have standalone in the name? Does that mean there is another way to create many diff editors that is more efficient?

什么都没有。 In Wikipedia 我找到了 standalone 的答案:

Standalone software may refer to:

  • Computer software that can work offline, i.e. does not necessarily require network connection to function.
  • Software that is not a part of some bundled software.
  • A program that run as a separate computer process, not an add-on of an existing process.
  • Standalone program, a program that does not require operating system's services to run.
  • A portable application, which can be run without the need for installation procedure.

这意味着 standalone 与单个实例无关,您可以拥有此编辑器的多个实例。但是您的计算机上必须有更多内存才能从此编辑器创建 100 个实例。这效率不高,因为你的内存中还有 100 个大 JavaScript 对象。

在其他用于显示已更改文件之间差异的服务上,它们仅使用 DOM 对象或使用 DOM 对象 + 来自创建此对象的大 JavaScript 对象的一个​​大实例,但不是来自大 JavaScript 对象的额外 100 个大实例。

根据此原则,在这种情况下,您可以使用我在下面推荐的解决方案中的代码,并在后台仅从该差异编辑器中清除一个实例。然后你必须把你所有的 100 个文件一个接一个地放到这个实例中,并在每种情况下从一个文件中复制 DOM 个对象:

  • <div class="editor original showUnused" ...
  • <div class="editor modified showUnused" ...

例如,您可以使用以下代码执行此操作:

var diffPartContainars = document.querySelector('#container').querySelectorAll('.showUnused'),
    editorOriginalPartHTML,
    editorModifiedPartHTML;

for(var i = diffPartContainars.length; i--;)
{
    var obj = diffPartContainars[i],
        cln = obj.className;

    if(cln.indexOf('editor original') > -1)
    {
        obj.removeAttribute('style');
        editorOriginalPartHTML = obj.outerHTML;
    }
    if(cln.indexOf('editor modified') > -1)
    {
        obj.removeAttribute('style');
        editorModifiedPartHTML = obj.outerHTML;
    }
}

然后您必须从每个 editorOriginalPartHTML 和 editorModifiedPartHTML 中删除以下 DOM 个对象:

  • <div class="invisible scrollbar horizontal" ...
  • <canvas class="decorationsOverviewRuler" ...
  • <div class="visible scrollbar vertical" ...

以及您不能使用的所有其他对象。当您将 editorOriginalPartHTMLeditorModifiedPartHTML 添加到您的 DOM 时,您就可以做到这一点。然后你可以从它的每个周围添加一个 div 对象,带有合适的 widthheightstyle="overflow:auto"。还有一件事你可以做更多:对于这个 div 对象中的每个你可以添加一个 onclickonmouseover 监听器,然后用你的差异编辑器实例替换这个 div 对象视图.

这只是我认为提高效率的一种方法。祝你好运!

推荐的高效解决方案

仅拥有此编辑器的一个实例并在单击如下文件名时加载新源的一种快速、舒适且高效的方法。

var diffEditor = null;
var filesContent =
{
    'SomeJavaScriptFile.js':
    {
        originalContent: 'alert("heLLo world!")',
        modifiedContent: 'alert("hello everyone!")',
        type: 'text/javascript'
    },
    'AnotherJavaScriptFile.js':
    {
        originalContent: 'function open(str)\n{\n\talert(str)\n}',
        modifiedContent: 'function output(value)\n{\n\tconsole.log(value)\n}',
        type: 'text/javascript'
    }
};

document.querySelector('#files').addEventListener('change', function(e)
{
    var fileName = this.options[this.selectedIndex].text,
        file = filesContent[fileName];

    openInDiffEditor(file);
});

function openInDiffEditor(file)
{
    if(!diffEditor)
        diffEditor = monaco.editor.createDiffEditor(document.querySelector('#container'));

    diffEditor.setModel({
        original: monaco.editor.createModel(file.originalContent, file.type),
        modified: monaco.editor.createModel(file.modifiedContent, file.type)
    });
}

//open the first file in select list:
var firstFileName = document.querySelector('#files').options[0].text;
openInDiffEditor(filesContent[firstFileName]);
<p>Please select one file on the left list to see the file differences after changes.</p>
<select id="files" size="3">
    <option selected>SomeJavaScriptFile.js</option>
    <option>AnotherJavaScriptFile.js</option>
</select>

<div id="container" style="height:100%;"></div>

并且您必须加载文件内容 AJAX。但是,如果你不明白如何加载它,请问我,我会写出来。

此推荐方案截图