我正在使用Windows 8 Metro應用程序,並且發現(即使在他們的示例應用程序中,我沒有觸及代碼),當您在頁面之間導航時,頂層「 default.html「獲取應用程序運行期間加載的每一個js和css文件。WinJS不卸載js/css
這使我很頭痛,因爲我的CSS在差異頁面之間發生衝突。我錯過了什麼,或者這是嚴重的錯誤?
我正在使用Windows 8 Metro應用程序,並且發現(即使在他們的示例應用程序中,我沒有觸及代碼),當您在頁面之間導航時,頂層「 default.html「獲取應用程序運行期間加載的每一個js和css文件。WinJS不卸載js/css
這使我很頭痛,因爲我的CSS在差異頁面之間發生衝突。我錯過了什麼,或者這是嚴重的錯誤?
不卸載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名稱空間以防止碰撞。這比手動刪除鏈接標記要容易得多,而且比完全導航會帶來更好的應用體驗。
它不是一個bug,它是WinJS tempaltes使用的默認應用程序模式的一部分。默認的WinJS模板使用單頁模型,這意味着使用PageNavigatorControl將所有內容加載到default.html中。因此,內存中一直存在單個DOM。如果您在普通瀏覽器中使用了類似的模式,則會看到相同的行爲。
如果需要,您可以使用更多傳統導航,使用多個頁面和傳統的href鏈接。這不是推薦的方法,但如果您嘗試使用該模型構建現有的Web資產,它可以使事情變得更簡單。
我得到的單頁模式,我只是想出MS是一個有點小聰明,當你導航遠離它們卸載內頁的資源。 – Endophage 2012-08-17 02:52:33
您可以通過查詢文檔中的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>
是的,我知道我可以這樣做,但這正是我試圖避免需要硬編碼。我可能只是切換到多頁實現,並沒有任何CSS的個別部分,每個母版頁將是一個模板,所有的CSS在一個單一的文件,然後加載的子頁面將不會有任何他們自己的CSS。 – Endophage 2012-08-17 16:29:47
這可能是一個約定名稱的形式給出了一個很好的解決方案:
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;
}
}
});
腳本文件不是這樣的問題,很容易命名函數不會碰撞或只是使用WinJS.Namespace,但是可以卸載css文件並且它似乎是明智的。事實上,似乎每個人都已經承認,命名空間的所有CSS類是走的路,這實際上是一個徹頭徹尾的破解......至少這是故意的,但長遠來說,我相信這是一個更多的事情MS要走了受到批評。 – Endophage 2012-08-17 22:48:24
我不確定除了在每個頁面加載時加載CSS文件,問題是什麼。樣本告訴你確保你的網頁名稱空間;這說得通。您可以使用LESS/SCSS來幫助命名空間,比如Web Essentials或Web Workbench。 – kamranicus 2012-12-10 21:28:06