使用CodeMirror外掛遇到的問題

打遊戲也要有夢想發表於2020-07-07

CodeMirror的正常使用:

//首先通過<script>標籤引入相應的js,這個就不必說了
var myCodeMirror = CodeMirror.fromTextArea(myTextArea,{
      key: "value"
});//就這麼簡單

問題一、CodeMirror在Bootstrap模態框下的使用不顯示程式碼

這個非常簡單

var myCodeMirror_Modal = CodeMirror.fromTextArea(document.getElementById("codetextarea"), {
    theme: "default",可以設定其他主題,但必須引入相應的css
    lineNumbers: true,
    mode: "text/javascript",可以設定其他語言,但必須引入相應的js
    smartIndent: true
});//構造CodeMirror例項
關鍵程式碼來了
$("#codeEditModal").on('shown.bs.modal.bs.modal', function () {//模態框顯示後觸發該事件
    myCodeMirror_Modal.refresh();//重新整理編輯器,這樣問題就解決了
});

問題二、如何使用clipboard複製CodeMirror裡面的程式碼

clipboard的正常使用:

<!--html-->
<input type="text" id="myInput" value="輸入內容" />
<button class="my-compy" data-clipboard-target="#myInput">複製文字框的內容</button>  <!--注意一下這個data-clipboard-target屬性-->

<textarea id="myContent">123456789</textarea>
<button class="my-compy" data-clipboard-target="#myContent">複製多行文字框的內容</button>
首先通過<script>標籤引入相應的js,這個就不必說了
//JavaScript
var clipboard = new ClipboardJS('.my-compy');//通過class名構造例項

clipboard.on('success', function(e) {
    alert("複製成功");
});

clipboard.on('error', function(e) {
    console.log(e);
    alert("失敗!");
});

問題:

<textarea id="myCode">$.ajax({})</textarea>
<button class="code-copy" data-clipboard-target="#myCode">複製多行文字框的內容</button>
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("myCode"), {
    theme: "default",
    lineNumbers: true,
    mode: "text/javascript",
    smartIndent: true
});//構造CodeMirror例項

var clipboard = new ClipboardJS('.code-copy');//通過class名構造例項

clipboard.on('success', function(e) {
    alert("複製成功");
});

clipboard.on('error', function(e) {
    console.log(e);
    alert("失敗!");
});

結果你會發現,可以複製程式碼,沒問題,但是不可以貼上複製的程式碼,那問題到底出現在了哪裡呢?
首先呢,排除clipboard外掛的問題,這個很簡單,隨便找個例子測試一下就行了,發現的確沒問題,可以複製,可以貼上。
那問題肯定是出現在CodeMirror上了。
折騰了很久,發現CodeMirror這個外掛的原理:
它是首先獲取textarea這個標籤裡面的內容,然後設定display:none;接著通過正規表示式,來解析textarea的內容,並在上面加上相應的樣式,最後在textarea標籤的後面插入新的內容。原理的確挺簡單的,但要真正做到,的確是不容易的!!!

問題就出現在這個display:none上,然後我測試了一下,給一個文字框設定display:none,clipboard可以複製,但無法貼上內容了。
總算找到了問題,那如何解決呢?
既然無法複製display:none的文字框的內容,那我可以通過CodeMirror的例項來獲取程式碼內容不就行了嗎?
答案:嗯,這樣的確便可以了,問題解決!!!
程式碼如下:

<textarea id="myCode">$.ajax({})</textarea>
<button class="code-copy">複製多行文字框的內容</button><!--在這裡不要設定data-clipboard-target-->
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("myCode"), {
    theme: "default",
    lineNumbers: true,
    mode: "text/javascript",
    smartIndent: true
});//構造CodeMirror例項

var clipboard = new ClipboardJS('.code-copy', {
    text: function (e) {
        var value = myCodeMirror.getValue();//重寫clipboard貼上的文字
        return value;
    }
});

clipboard.on('success', function(e) {
    alert("複製成功");
});

clipboard.on('error', function(e) {
    console.log(e);
    alert("失敗!");
});

這樣,便解決了問題,但一想:這樣不行啊,如果我要構造多個CodeMirror,那複製的話,需要複製哪個文字框裡面的程式碼呢?

問題三、如何一次性構造多個CodeMirror

//遍歷class為code_mirror_textarea的textarea
$(".code_mirror_textarea").each(function () {
    let textareaId = $(this).attr("id");//獲取textarea的id
    let codeLanguage = $(this).data("codelanguage");//獲取textarea的language mode,這個需要提前給每個textarea通過data-codelanguage賦值的
    //console.log(textareaId, codeLanguage);
    myCodeEditor(textareaId, codeLanguage);//分別構造CodeMirror的例項
});


function myCodeEditor(textareaId, codeLanguage) {
    var editor = CodeMirror.fromTextArea(document.getElementById(textareaId), {
        theme: "default",
        lineNumbers: true,
        mode: codeLanguage,
        smartIndent: true
    });
} 

問題四、批量構造多個CodeMirror,那如何獲取CodeMirror的例項呢?

官網文件並沒有提供獲取CodeMirror例項的API。
但還是有辦法滴,小爺我就是這麼6!!!

function myCodeEditor(textareaId, codeLanguage) {
    var editor = CodeMirror.fromTextArea(document.getElementById(textareaId), {
        theme: "default",
        lineNumbers: true,
        mode: codeLanguage,
        smartIndent: true
    });
    $("#" + textareaId + "").data("CodeMirrorInstance", editor);//將CodeMirror例項儲存在textarea對應的CodeMirrorInstance裡面就可以了
} 

//然後怎麼獲取CodeMirror例項呢?
var myCodeMirror = $("#" + textareaId + "").data("CodeMirrorInstance");//接下來便可以通過myCodeMirror來呼叫相應的API了
var value = myCodeMirror.getValue();//獲取CodeMirror值

騷年,不行了吧,趕緊點贊關注,全是乾貨,讓你少走很多坑!!!

相關文章