JavaScript與.Net MVC的一次糾結之旅

首先我想實現的效果是這樣的:
這裏寫圖片描述
在下拉列表中選擇要添加的題型,下面根據我選擇的題型動態的載入不同格式的編輯器,比如我選擇單項選擇題,下面的編輯器應該像圖中那樣,包含一個題乾的編輯框和四個選項的編輯框,並且每個選項前有一個radio button來讓我選擇哪個是正確的答案。
每種類型的編輯器我都採用單獨的partial view來實現。最終將根據題型將不同的編輯器視圖載入下面的div標籤中

<div id="addquestionarea">
</div>

自然而然的我想到了給下拉框的change事件綁定一個函數來動態改變這個div標籤中的視圖:

$(document).ready(function()
{
    $("#typeList").change(function () {
        changeQuestionEditor();
    });

});

在changeQuestionEditor()這個函數中,我用Ajax來請求部分視圖。

function changeQuestionEditor() {
    var unitTestId = $("#unitTestId").val();
    $.ajax({
        url: '../SingleChoiceManager/Create',
        data: { unitTestId: unitTestId },
        type: "GET",

        async: false,
        dataType: "html",
        success: function (data) {
            $("#addquestionarea").empty();
            $("#addquestionarea").html(data);
        }
    });

愉快的寫好代碼後馬上運行了一下,理想中是那樣的,可是事實確是這樣的:
這裏寫圖片描述
發生了神馬?我馬上右鍵審查元素:
這裏寫圖片描述
源文件裏是這樣的:

<!-- 配置文件 -->
<script type="text/javascript" src="/Scripts/ueditor1_4_3-utf8-net/ueditor.config.js"></script>
<!-- 編輯器源碼文件 -->
<script type="text/javascript" src="/Scripts/ueditor1_4_3-utf8-net/ueditor.all.js"></script>
<script type="text/javascript" src="/Scripts/ueditor1_4_3-utf8-net/kityformula-plugin/addKityFormulaDialog.js" charset="UTF-8"></script>
<script type="text/javascript" src="/Scripts/ueditor1_4_3-utf8-net/kityformula-plugin/getKfContent.js" charset="UTF-8"></script>
<script type="text/javascript" src="/Scripts/ueditor1_4_3-utf8-net/kityformula-plugin/defaultFilterFix.js" charset="UTF-8"></script>
<!-- 自定義 -->
<script type="text/javascript" src="~/Scripts/addQuestion.js" charset="utf-8"></script>
<script src="~/Scripts/SingleChoiceManager/createSingleChoice.js"></script>


<!-- 層疊樣式表 -->
<link href="~/Content/addquestion.css" rel="stylesheet" type="text/css" />
<!-- 加載編輯器的容器 -->

我的JavaScript都被狗吃了麼?!!

然後我發現,只要把

$("#addquestionarea").html(data);

改爲

document.getElementById("addquestionarea").innerHTML = data;

引用的外部JavaScript就又重新出現了,原因不明,有知情者煩請不吝賜教。

雖然引用的外部JavaScript在審查元素時都能看到了,但是似乎依然沒有執行js

然後百般求索,我發現了下面這篇博客:
IE 和 Firefox 可以通過特定方法使 innerHTML 方法載入的 SCRIPT 標籤中的 JavaScript 代碼在頁面加載後也可以執行
裏面說“所有瀏覽器中,默認情況下通過 innerHTML 方法動態插入到頁面中的 SCRIPT 標籤中的腳本代碼均不能被執行。”
樓主針對IE和Firefox提出了兩種方法解決這個問題:

  1. IE:給SCRIPT 元素加上 defer 屬性可以讓腳本延遲執行
    這真是簡單實用啊,剛準備嘗試,不小心看到了這句話“Chrome Safari Opera 不支持 defer 屬性”,果然業界良心啊!有木有!!
  2. Firefox:先把div標籤從文檔樹上拿下來,把包含局部頁面的html通過innerHTML或 JQuery的.html()放進去,然後再重新把div標籤掛到文檔樹上。
    這個似乎也不錯,於是又一陣亂試,最後還是沒有搞定。

於是決定靜下心來把樓主的文章看完,到結尾的時候,樓主語重心長的說道:
“上面提到的 IE 及 Firefox 中使通過 innerHTML 方法動態插入的 SCRIPT 元素中腳本執行的方法均比較特殊,是利用了瀏覽器的 Bug,或者是利用了瀏覽器提供的特性。而 innerHTML 方法只是用來插入 HTML 代碼,並不能使其中包含的腳本代碼執行。
爲了達到最好的兼容性,應避免利用瀏覽器特性及 Bug 使 innerHTML 插入的 SCRIPT 中的代碼執行。所以上述 IE 和 Firefox 中的方法不可行。同時這種做法具有安全隱患。
對於可控來源的動態腳本,使用 createElement 創建 SCRIPT 元素並追加至頁面的文檔樹中,以保證動態腳本的執行。”

最後一句話又給了我一絲希望!

然後我把代碼改成了醬紫:

function changeQuestionEditor() {
    var unitTestId = $("#unitTestId").val();
    $.ajax({
        url: '../SingleChoiceManager/Create',
        data: { unitTestId: unitTestId },
        type: "GET",

        async: false,
        dataType: "html",
        success: function (data) {
            addAllScripts();
            $("#addquestionarea").empty();
            $("#addquestionarea").html(data);
        }
    });    
}

其中的addAllScripts()方法用來將所有的JavaScript追加到文檔中,代碼如下:

function addAllScripts()
{
    var head = document.getElementsByTagName("head")[0];

    var script1 = document.createElement("script");
    alert(document.location.host);
    script1.setAttribute("src", document.location.host+"/Scripts/ueditor1_4_3-utf8-net/ueditor.config.js");
    head.appendChild(script1);

    var script2 = document.createElement("script");
    script2.setAttribute("src", document.location.host+"/Scripts/ueditor1_4_3-utf8-net/ueditor.all.js");
    head.appendChild(script2);

    //以下省略
}

這下總可以了吧?

生活如果不讓人失望那還有什麼意思?!不說了,都在圖裏了:
這裏寫圖片描述

誰能告訴我啥叫net::ERR_UNKNOWN_URL_SCHEME啊?

在網上找答案無果,自己猜測問題肯定是在JavaScript的路徑上,於是將設置script中src屬性的代碼改成下面這樣:

script1.setAttribute("src", "/Scripts/ueditor1_4_3-utf8-net/ueditor.config.js");

即刪掉了document.location.host,果然不報錯了,但是依然沒有出現我想看到的結果,可見js還是沒有執行。

後記:

最後結束這次糾結的方案是,先把partial view中的外部js引用全部移到主頁面當中,然後刷新整個頁面,並通過url把用戶當前選中的選項傳給刷新後的頁面,再根據選中的值來動態加載不同的編輯器partial view。當然這樣刷新整個頁面的性能肯定不如局部刷新,這也只是我的一個權宜之計。如果誰知道如何讓局部刷新的內容中包含的JavaScript可以執行的方法,懇請不吝賜教!其中還會遇到UEditor不能二次加載的問題,解決方案在我的另一篇博客中:UEditor不能重新加載的問題

發佈了44 篇原創文章 · 獲贊 48 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章