Win8出來時參加了一個活動,寫了一個APP,後來微軟那邊沒什麼動靜了,就一直沒怎麼管了,最近系統升級從Consumer Preview版升級到 Release Preview 版,VS也升級到 Visual Studio 2012 RC 後,才發現原來的APP不能運行了,於是折騰了好一陣子才OK,現在做個小結,希望可以幫到遇到相同問題的朋友。
一、WinJS版本修改
Windows 8 Consumer Preview版中WinJS是0.6版,Release Preview 版中WinJS是1.0版,所以要把項目中的WinJS進行升級。
這個比較簡單,大家直接按官方給出的步驟做就OK了:http://msdn.microsoft.com/en-us/library/windows/apps/JJ126963.aspx
極少數情況下你的VS2012中沒有1.0版的WinJS:
遇到這種情況說明你的VS沒有裝好,修複安裝就OK了。
二、滿屏,半屏,還有小屏的頁面狀態方法的修改
這個地方我遇到的癥狀就是程式閃一下就沒了,不能開啟。
解決方案就是把 navigator.js 中的:
appView.getForCurrentView().onviewstatechanged = this._viewstatechanged.bind(this);
改為:
window.onresize = this._viewstatechanged.bind(this);
上面的方案來自:http://social.msdn.microsoft.com/Forums/et-EE/winappswithhtml5/thread/d02bf608-675d-4676-a4ec-3ccbc64671f1
但僅僅改這一個地方是不完美的,因為這個檔案裡還有與這個相關的代碼。所以還要把這行代碼稍後的:
_viewstatechanged: function (eventObject) { (this._updateLayout.bind(this.pageControl))(this.pageElement, eventObject.viewState);},
改為(或直接添加下面這段代碼也可以):
_resized: function (args) { if (this.pageControl && this.pageControl.updateLayout) { this.pageControl.updateLayout.call(this.pageControl,
this.pageElement, appView.value, this.lastViewstate); } this.lastViewstate = appView.value;},
三、Share功能代碼的修改
由於我的應用程式在每個詳細頁提供了Share功能,如果大家的應用中沒有這個功能就不用看這一條了。
這個錯誤的癥狀為開啟第二個有share功能的頁面(或本頁面開啟兩次)就會出現類似下面的錯誤:
- SCRIPT14: Exception was thrown but not handled in user code at line 112, column 17 in ms-appx://3fa1d0d0-fb4a-48c6-8e10-f40028f54bc3/js/itemDetailPage.js
0x8000000e - JavaScript runtime error: A method was called at an unexpected time.
WinRT information: An event handler has already been registered
File: itemDetailPage.js, line: 112 column: 17
在WinJS 0.6 版中 Share的代碼大致是這樣寫的:
var dtm = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();dtm.addEventListener("datarequested", onDataRequested);function onDataRequested(e) { var request = e.request; request.data.properties.title = item.title; request.data.properties.description = "Test"; request.data.setText(item.content);}
代碼中的item是當前頁面上繫結資料項(建立一個Grid App項目,在itemDetail.js裡就有)。
在WinJS1.0裡報的錯大致可以看出是說 datarequested 事件已經註冊了,所以會出錯。
一開始我嘗試的是在添加事件之前先移除這個事件,但依然出錯,後來想找到頁面unload方法,想在這個方法裡面移除事件,但貌似WinJS.UI不支援這個方法,試了好多次都不行後,找到了新的方案,就是添加一個全域變數作為標識,只註冊一次。、
但由於上面代碼裡的item是當前頁面上繫結資料項,這就導致了Share的資料是第一次開啟詳細頁的資料,不會改變。最後直接把item.title和item.content改為從頁面上擷取,終於OK了,代碼如下:
var dtm = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();if (!isDatarequested) { dtm.addEventListener("datarequested", onDataRequested); isDatarequested = true;}function onDataRequested(e) { var request = e.request, title = document.querySelector("article .item-title").textContent, content = document.querySelector("article .item-content .content").textContent; request.data.properties.title = title; request.data.properties.description = "Test"; request.data.setText(content);}
代碼中的 isDatarequested 是一個全域bool變數,初始值為 false 。
目前的方案可以解決問題,但還是不太明白為什麼會出現重複註冊事件問題,如果有朋友知道請不吝指點。
四、應用掛起和啟動處理時的最佳化
注意,這一點是最佳化,不是錯誤,所以如果你不修改也不會出錯。
在WinJS0.6版中default.js裡有總分代碼是這樣的:
var app = WinJS.Application;app.onactivated = function (eventObject) { if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) { WinJS.UI.processAll(); }};
在WinJS1.0中要改為這樣:
var app = WinJS.Application;var activation = Windows.ApplicationModel.Activation;var nav = WinJS.Navigation;WinJS.strictProcessing();app.addEventListener("activated", function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } if (app.sessionState.history) { nav.history = app.sessionState.history; } args.setPromise(WinJS.UI.processAll().then(function () { if (nav.location) { nav.history.current.initialPlaceholder = true; return nav.navigate(nav.location, nav.state); } else { return nav.navigate(Application.navigator.home); } })); }});