2012-08-17 69 views
7

我正在使用Windows 8 Metro應用程序,並且發現(即使在他們的示例應用程序中,我沒有觸及代碼),當您在頁面之間導航時,頂層「 default.html「獲取應用程序運行期間加載的每一個js和css文件。WinJS不卸載js/css

這使我很頭痛,因爲我的CSS在差異頁面之間發生衝突。我錯過了什麼,或者這是嚴重的錯誤?

回答

13

不卸載JavaScript和CSS是故意的選擇,而不是意外或疏忽。

首先,瞭解頁面控件純粹是JavaScript構造 - 瀏覽器引擎完全不瞭解它們。瀏覽器只能看到由腳本動態生成的一大塊DOM。

網絡平臺不允許您卸載腳本文件 - 一旦它們加載到上下文中,它們就會永遠存在。

對於CSS,他們可能試圖刪除標籤,但它會打開一堆蠕蟲。根據導航到的訂單頁面的不同,最終可能會在同一應用中應用不同的樣式。如果兩頁涉及相同的樣式表會怎麼樣?你有兩次添加相同的鏈接標籤嗎?你刪除哪一個?

這是一團糟。相反,WinJS保證腳本和樣式表只會在第一次被引用時加載一次。因此,您可以讓應用中的每個頁面引用「myStyles.css」,並且只會加載一次(並且只會有一個樣式標籤)。

那麼你怎麼做才能防止你看到的問題?首先,請記住,您正在構建應用程序,而不是任意增加新內容的網站。決定你的一般風格和課程。將共享樣式放在default.css中,並從default.html文件中引用它。

對於單獨的頁面,最簡單的做法是在頁面名稱的前面添加樣式。相反的:

<div class='intro'></div> 

<div class='page1-intro'></div> 

然後你保證,以避免衝突。

如果您通過ID引用頁面元素,那麼不要這樣做。在頁面中使用ID會導致各種可能的奇怪現象(如果你同時渲染兩次相同的頁面控件,那麼這個ID還不存在,直到頁面加載到DOM之後,這個ID纔會存在,這意味着data-win-選項引用ID不起作用)。但是,如果你堅持,再次考慮在頁面前添加ID。

基本上,設置ad-hoc名稱空間以防止碰撞。這比手動刪除鏈接標記要容易得多,而且比完全導航會帶來更好的應用體驗。

+0

腳本文件不是這樣的問題,很容易命名函數不會碰撞或只是使用WinJS.Namespace,但是可以卸載css文件並且它似乎是明智的。事實上,似乎每個人都已經承認,命名空間的所有CSS類是走的路,這實際上是一個徹頭徹尾的破解......至少這是故意的,但長遠來說,我相信這是一個更多的事情MS要走了受到批評。 – Endophage 2012-08-17 22:48:24

+0

我不確定除了在每個頁面加載時加載CSS文件,問題是什麼。樣本告訴你確保你的網頁名稱空間;這說得通。您可以使用LESS/SCSS來幫助命名空間,比如Web Essentials或Web Workbench。 – kamranicus 2012-12-10 21:28:06

3

它不是一個bug,它是WinJS tempaltes使用的默認應用程序模式的一部分。默認的WinJS模板使用單頁模型,這意味着使用PageNavigatorControl將所有內容加載到default.html中。因此,內存中一直存在單個DOM。如果您在普通瀏覽器中使用了類似的模式,則會看到相同的行爲。

如果需要,您可以使用更多傳統導航,使用多個頁面和傳統的href鏈接。這不是推薦的方法,但如果您嘗試使用該模型構建現有的Web資產,它可以使事情變得更簡單。

+0

我得到的單頁模式,我只是想出MS是一個有點小聰明,當你導航遠離它們卸載內頁的資源。 – Endophage 2012-08-17 02:52:33

0

您可以通過查詢文檔中的link元素來解決此問題,該元素導入樣式並禁用不需要的樣式。您需要確保您沒有禁用項目中的MS CSS文件和default.css文件,假設您使用它來爲您的應用程序定義常用樣式。

下面是一個示例,告訴你如何去做。這是一個名爲page2.html的文件,當通過WinJS.Pages.UI.render方法加載時,將找到並禁用它不需要的link元素。它確保page2.css文件已啓用,並保留它僅僅忽略的文件列表。我把它放在ready處理函數中,但我傾向於在WinJS.Navigation事件的處理程序中使用這種技術,並依靠一致的文件命名來獲得我想要的結果。

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <title>UnloadCSS</title> 

    <!-- WinJS references --> 
    <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" /> 
    <script src="//Microsoft.WinJS.1.0/js/base.js"></script> 
    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script> 

    <!-- UnloadCSS references --> 
    <link href="/css/page2.css" rel="stylesheet" /> 

<script> 
    WinJS.UI.Pages.define("/page2.html", { 
     ready: function() { 

      var ignoreList = ["/css/ui-dark.css", "/css/ui-light.css", "/css/default.css"]; 
      var myCSS = "/css/page2.css"; 

      WinJS.Utilities.query("link").forEach(function (linkElem) { 
       if (linkElem.href.indexOf(myCSS) > -1) { 
        linkElem.disabled = false; 
       } else { 
        var ignore = false; 
        ignoreList.forEach(function (ignoreItem) { 
         if (linkElem.href.indexOf(ignoreItem) > -1) { 
          ignore = true; 
         } 
        }); 
        if (!ignore) { 
         linkElem.disabled = true; 
        } 
       } 
      }); 
     } 
    }); 
</script> 
</head> 
<body> 
    <button>Change </button> 
</body> 
</html> 
+0

是的,我知道我可以這樣做,但這正是我試圖避免需要硬編碼。我可能只是切換到多頁實現,並沒有任何CSS的個別部分,每個母版頁將是一個模板,所有的CSS在一個單一的文件,然後加載的子頁面將不會有任何他們自己的CSS。 – Endophage 2012-08-17 16:29:47

0

這可能是一個約定名稱的形式給出了一個很好的解決方案:

var currentPage = Application.navigator.pageControl.uri.replace("ms-appx://" + Windows.ApplicationModel.Package.current.id.name.toLowerCase(), ""); 
var currentCss = currentPage.replace(".html", ".css"); 

var ignoreList = ["/css/ui-dark.css", "/css/ui-light.css", "/css/default.css"]; 

WinJS.Utilities.query("link").forEach(function (linkElem) { 
    if (linkElem.href.toLowerCase().indexOf(currentCss) > -1) { 
     linkElem.disabled = false; 
    } else { 
     var ignore = false; 
     ignoreList.forEach(function (ignoreItem) { 
     if (linkElem.href.toLowerCase().indexOf(ignoreItem.toLowerCase()) > -1) { 
      ignore = true; 
     }}); 
     if (!ignore) { 
      linkElem.disabled = true; 
     } 
     } 
});