【问题标题】:Multiple instances of CodeMirror textarea on the same page同一页面上的多个 CodeMirror textarea 实例
【发布时间】:2017-12-21 22:09:43
【问题描述】:

我正在尝试为求职面试问题制作一个小项目,并在页面上有一堆带有答案和代码示例的问题。每个都在 Materialize.css 的 .collapsible div 中,单击时会显示答案和代码示例。

解决此问题的最佳方法是什么?我尝试将初始化程序放入一个函数中,从 DOM 中获取我所有的文本区域,循环它们并将它们变成 CodeMirror 文本区域。

$(document).ready(function(){

  var blocks = document.getElementsByClassName('code-block');

  function createEditorFrom(selector) {
    let editor = CodeMirror.fromTextArea(selector, {
      lineNumbers : false,
      mode: "swift",
    });
  }

  for (var x = 0; x < blocks.length; x++) {
    createEditorFrom(blocks[x]);
  }

  // Callback for Collapsible open
  $('.collapsible').collapsible({
    onOpen: function() { 
      // call editor.refresh()?
    },
  });

});

这确实有效,但我觉得这不是解决这个问题的一种非常优雅的方式。有没有更好的方法来做到这一点?

问题:

  1. 有没有更好的方法来创建所有 CodeMirror 文本区域?
  2. 编辑器中的代码在单击之前不会出现。我所做的一切都无法让它发挥作用。调用 editor.refresh()(使用 setTimeout)和 autorefresh: true。

【问题讨论】:

    标签: javascript html codemirror


    【解决方案1】:

    无论如何,您必须做的一件事是保留对您的 CodeMirror 实例的引用(例如,获取/设置它们的值),因此 createEditorForm 将必须返回 CodeMirror 实例,并且您可以例如将它们推送到一个数组在循环中:

    function createEditorFrom(selector) {
      return CodeMirror.fromTextArea(selector, {
        lineNumbers : false,
        mode: "swift",
      });
    }
    
    let codeblocks = [];
    for (var x = 0; x < blocks.length; x++) {
      codeblocks.push({
         CM: createEditorFrom(blocks[x]), 
         el: blocks[x]
      });
    }
    

    我遇到了类似的问题“编辑器中的代码在单击之前不会出现”,我什至在解决方案旁边写了一条评论。转换为您的实现将是:

    function createEditorFrom(selector) {
      var instance = CodeMirror.fromTextArea(selector, {
        lineNumbers : false,
        mode: "swift",
      });
      // make sure the CodeMirror unit expands by setting a null character
      instance.setValue('\0');
      instance.setValue('');
      return instance;
    }
    

    为了它的价值,我还使用了一些 CSS 调整来确保一致的初始和最大高度渲染:

    /* CodeMirror */
    .CodeMirror { height: auto; overflow: auto; max-height: 250px; }
    .CodeMirror-scroll { height: auto; min-height: 24px; }
    

    有没有更好的方法来创建所有 CodeMirror 文本区域 [比通过它们循环]?

    是的,如果它们在页面加载时不可见,您可以延迟初始化它们(实际上我认为最好仅在 &lt;textarea&gt; 的父节点可见时才初始化它们,我我不确定 CodeMirror 是否需要渲染信息(如 Element.getBoundingClientRect),例如只加载它们的可折叠父级的 onOpen

    【讨论】:

    • 一些事情。 1) 我不需要对任何文本区域的引用,因为它们是在我的 Rails 应用程序中动态呈现的。 2)您关于必须单击文本区域以显示代码的回答对我的情况没有帮助,但我感谢您的帮助。 3)我真的没想过在折叠式打开时初始化它们,所以这就是我采取的路线,非常感谢。
    • @TaylorA.Leach ah 2) 值得一试。对于 1),当使用 CodeMirrorinstance.getValue() 编辑后需要保存数据时,您需要一个参考,或者我错过了什么
    • 我没有在我的情况下使用 getValue()。内容是在实际 textarea 内的 rails 中动态生成的。
    【解决方案2】:

    当折叠式打开时,我最终初始化了每一个。这可行,但我想如果同一个可折叠文件中有多个 CodeMirror 文本区域,则需要对其进行调整。

    我还添加了一个检查,否则当可折叠打开,然后关闭,然后重新打开时,它会创建一个重复的文本区域。

    $(document).ready(function(){
    
      $('.collapsible').collapsible({
        onOpen: createCodeBlock
      });
    
      function createCodeBlock(target) {
        var card     = target.context.parentElement.parentElement;
        var textarea = card.getElementsByClassName('code-block')[0];
    
        // Placeholder class that prevents the duplicate creation of
        // the same textarea when the collapsible is closed then reopened.
        if (!textarea.classList.contains("created")) {
          CodeMirror.fromTextArea(textarea, {
            lineNumbers: false,
            mode: "swift",
          });
          textarea.className += "created";
        }
      }
    
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-10
      相关资源
      最近更新 更多