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

时间:2014-06-11 15:17:38

标签: windows-8 windows-runtime windows-store-apps windows-8.1 winjs

我有一个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');        
    });

1 个答案:

答案 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的调用,你应该很好。