Windows 8 在WinJS中重新加载页面无法附加事件处理程序

Windows 8 在WinJS中重新加载页面无法附加事件处理程序,windows-8,windows-runtime,windows-store-apps,windows-8.1,winjs,Windows 8,Windows Runtime,Windows Store Apps,Windows 8.1,Winjs,我有一个WinJS应用程序(一个使用HTML/JS而不是C#/XAML的Windows8.1应用程序) 我在我的default.html中实现了一个自定义导航栏,其中一些按钮附带了click事件监听器。每个处理程序使用与导航按钮对应的页面url调用nav.navigate() 我的一个页面(称之为/pages/myPage/myPage.html)上有几个按钮。在页面的ready功能中,每个按钮都绑定了一个单击事件侦听器。当在多个页面之间导航时,这种方法可以很好地工作 但是,如果我在myPage

我有一个WinJS应用程序(一个使用HTML/JS而不是C#/XAML的Windows8.1应用程序)

我在我的
default.html
中实现了一个自定义导航栏,其中一些按钮附带了click事件监听器。每个处理程序使用与导航按钮对应的页面url调用
nav.navigate()

我的一个页面(称之为
/pages/myPage/myPage.html
)上有几个按钮。在页面的
ready
功能中,每个按钮都绑定了一个单击事件侦听器。当在多个页面之间导航时,这种方法可以很好地工作

但是,如果我在
myPage
(使用工作按钮单击处理程序)上,并再次单击
myPage
的导航栏按钮,则页面看起来会重新加载。似乎调用了
ready
函数(即执行其中的it console.log语句),但页面上的按钮似乎完全失去了其单击处理程序

如果我导航到另一个页面,然后再导航回,按钮会再次正常工作。但无论我做什么,当我在
myPage
上时,通过导航到自身(
nav.navigate(“/pages/myPage/myPage.html”)
来“重新加载”页面都会导致我的点击处理程序丢失

为什么会发生这种情况?调用了My
ready
函数,但不知何故,单击处理程序从未重新连接

下面是
myPage
的ready函数:

    ready: function (element, options) {
        document.getElementById("myButton").addEventListener("click", this.myButtonClicked);
    },
下面是
myPage
nav按钮的单击事件侦听器的外观(此代码位于
default.js
):


WinJS中的页面导航只是DOM替换的问题。当您进行nav时,目标“页面”内容将加载到DOM中,然后卸载上一个“页面”内容。您可以在navigator.js中的_导航方法中看到这一点。它为正在加载的页面创建一个新元素,呈现其中的片段,然后卸载旧页面

但是,新页面的ready方法是在卸载旧页面之前调用的(这是WinJS 2.0中的一个更改,因为WinJS 1.0在调用ready之前卸载了旧页面)。结果是,当您导航到已加载的同一页面时,当您加载myPage.html(B)时,myPage.html(A)位于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进行比较。不管怎样


无论如何,使用此功能,将对nav.navigate的调用替换为navigateIfDifferent,您应该会很好。

啊,谢谢!这完全可以解释。为什么这一变化使它成为WinJS2?它看起来相当不直观(旧的行为更有逻辑意义),不完全确定它为什么会改变(可能是优化和不同类型的代码结构)。在任何情况下,WinJS现在都是开源的,因此如果有足够的pull请求,它可能会更改回原来的版本。只需向WinJS存储库提交一个问题(对于其他有兴趣看到逻辑行为恢复的人!):
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);
    }
}