我有一个WinJS应用程序(使用HTML / JS的Windows 8.1应用程序,而不是C#/ XAML)。
我在我的default.html
中实现了一个自定义导航栏,其中一些按钮附有点击事件监听器。每个处理程序使用与导航按钮对应的页面的URL调用nav.navigate()
。
我的一个页面(称为/pages/myPage/myPage.html
)上面有几个按钮。每个按钮都有一个点击事件监听器,在页面的ready
功能中绑定到它。这在几个页面之间导航时工作正常。
但是,如果我在myPage
上(使用工作按钮点击处理程序)并再次单击myPage
的导航栏按钮,该页面就会重新加载。似乎调用了ready
函数(即它中的console.log语句被执行),但页面上的按钮似乎完全丢失了它们的点击处理程序!
如果我导航到另一个页面,然后导航回来,按钮再次正常工作。但无论我做什么,重新加载"页面导航到自身(nav.navigate("/pages/myPage/myPage.html")
时myPage
)导致我的点击处理程序丢失。
为什么会这样?我的ready
函数被调用,但不管怎样,点击处理程序永远不会被重新附加。
以下是myPage
的就绪功能:
ready: function (element, options) {
document.getElementById("myButton").addEventListener("click", this.myButtonClicked);
},
这里是myPage
导航按钮的点击事件监听器的样子(此代码位于default.js
中):
myPageNavButton.addEventListener("click", function () {
nav.navigate('/pages/myPage/myPage.html');
});
答案 0 :(得分:1)
WinJS中的页面导航只是DOM替换的问题。当您执行导航时,目标“页面”内容将加载到DOM中,然后卸载先前的“页面”内容。您可以在_navigating方法中的navigator.js中看到这一点。它为正在加载的页面创建一个新元素,在其中呈现该片段,然后卸载旧页面。
然而,在卸载旧页面之前调用新页面的ready方法(这是WinJS 2.0中的更改,因为WinJS 1.0在调用ready之前卸载了旧页面)。这样做的结果是,当您导航到已加载的同一页面时,myPage.html(A)在加载myPage.html(B)时位于DOM中。当您在ready方法中执行代码时,getElementById将在myPage.html(A)中找到按钮,因此您将处理程序附加到该元素。但是从准备好后返回之后,myPage.html(A)被卸载,因此您丢失了处理程序。而且因为你从未将处理程序附加到myPage.html(B)中的按钮,所以它们只是惰性的。
那么你能做些什么呢?在我看来,最好的解决方案是避免首先导航到同一页面,因为从长远来看,它只是充满了其他危险。要执行此操作,请将您的调用包装到nav.navigate,并检查您是否已经在目标页面上。这是一个执行该功能的函数的实现:
function navigateIfDifferent(target) {
var page = document.getElementById("contenthost").winControl.pageControl;
var fullTarget = "ms-appx://" + Windows.ApplicationModel.Package.current.id.name + target;
if (fullTarget !== page.uri) {
WinJS.Navigation.navigate(target);
}
}
这假设您正在使用的PageControlNavigator控件位于default.html中名为“contenthost”的div中(这是VS模板为您提供的)。我当时正在做的是为目标页面构建完整的包内URI,并将其与当前页面控件的uri进行比较,这也是一个完整的包内URI。您还可以从当前页面URI中剥离ms-appx://部分并与目标URI进行比较。无论哪种方式。
无论如何,使用此功能,用navigateIfDifferent替换你对nav.navigate的调用,你应该很好。