AngularJS:为什么 $scope 数据不会在 ui-router 状态更改后持续存在?
AngularJS: why does $scope data not persist over a ui-router state change?
我有两个视图,每个视图都有一个控制器,每个视图代表一个 UI-路由器状态。
如果我在一个控制器中设置 $scope
个变量,改变状态,然后返回,变量不再包含分配的值。
我可以通过使用 as 服务来存储数据,从而在状态更改时保留数据,所以我的代码可以正常工作。
我想每次ui-router
切换状态都会破坏旧状态的对象并实例化新状态的对象。
我很好奇为什么要这样设计。谁能解释一下?
正如您所说,AngularJS 带有路由的控制器背后的想法是它们只与当前正在使用的对象相关。在这种情况下,路由被视为树中的一个节点,如果您从任何一个节点遍历到任何其他非子节点,那么假设旧数据仍然相关可能是不合逻辑的。但是,如果您确实在子状态中导航,那么保存数据再次变得合乎逻辑。
例子
假设您有一个看起来像社交媒体网站的应用程序。您有一个包含消息列表的 feed
状态,一个用于添加您自己的 post 的 create
状态,以及 contacts
应用程序。后一个有一个用于列出联系人的子状态 (contacts.list
) 和一个用于查看单个联系人的子状态 (contacts.view
):
feed -------- create -------- contacts
______|______
/ \
/ \
/ \
contacts.list contacts.view
滚动浏览提要,如果您决定创建自己的消息,然后想返回到您的提要,您可能想要显示您离开的地方。但是,这需要在内存中存储加载的 posts 和评论,以及页面上的位置和加载的图像。由于您的提要是动态的,并且已经查看过的 post 可能不会再次显示,因此刷新提要并重新开始可能更合乎逻辑。
相比之下,如果您转到联系人页面 - 并因此被重新路由到 contacts.list
,这些条目可能已排序,无论是按字母顺序还是按添加日期。如果您滚动浏览并决定查看某个联系人,那么当您回来时顺序可能会相同,并且您可能不会有任何新联系人,因此最好从您离开的地方继续。这可以通过将联系人列表加载到父状态来完成,可能带有最后查看的联系人的 ID,以查看您在哪里。这方面的一个例子可能是面包屑元素,它指示潜在路径树中的路径。
如果你从一个状态移动到另一个状态,你就在节点之间创建了一条路径,比如说你 离开 create
到 进入 feed
,或者您 输入 contacts
然后 contacts.list
。如果您从 contacts.view
移动到 contacts.list
,您 保留 contacts
,因此该控制器将继续使用 - 它永远不会被销毁。
回溯历史与正常导航
不过,这里遗漏了一个重要的区别,即通过移动应用程序中的向后箭头或通过浏览器上的后退按钮向后移动之间的区别。这与单击按钮转到主页形成对比,因为它假定主页已在过去加载。
在许多移动应用程序中,导航被视为一种流程,尽可能避免使用大菜单。相反,更多的重点放在创建历史记录上,因此无论它们在树中的哪个位置,都可以通过向左滑动或始终单击相同的按钮来重新访问以前访问过的页面。此外,对于移动应用程序,无法假定可靠的网络连接,因此最好保持旧页面不变,而不是从服务器刷新和重新获取。这也是为什么像 Ionic 这样基于 AngularJS 的框架提供特定页面历史功能的原因。
我有两个视图,每个视图都有一个控制器,每个视图代表一个 UI-路由器状态。
如果我在一个控制器中设置 $scope
个变量,改变状态,然后返回,变量不再包含分配的值。
我可以通过使用 as 服务来存储数据,从而在状态更改时保留数据,所以我的代码可以正常工作。
我想每次ui-router
切换状态都会破坏旧状态的对象并实例化新状态的对象。
我很好奇为什么要这样设计。谁能解释一下?
正如您所说,AngularJS 带有路由的控制器背后的想法是它们只与当前正在使用的对象相关。在这种情况下,路由被视为树中的一个节点,如果您从任何一个节点遍历到任何其他非子节点,那么假设旧数据仍然相关可能是不合逻辑的。但是,如果您确实在子状态中导航,那么保存数据再次变得合乎逻辑。
例子
假设您有一个看起来像社交媒体网站的应用程序。您有一个包含消息列表的 feed
状态,一个用于添加您自己的 post 的 create
状态,以及 contacts
应用程序。后一个有一个用于列出联系人的子状态 (contacts.list
) 和一个用于查看单个联系人的子状态 (contacts.view
):
feed -------- create -------- contacts
______|______
/ \
/ \
/ \
contacts.list contacts.view
滚动浏览提要,如果您决定创建自己的消息,然后想返回到您的提要,您可能想要显示您离开的地方。但是,这需要在内存中存储加载的 posts 和评论,以及页面上的位置和加载的图像。由于您的提要是动态的,并且已经查看过的 post 可能不会再次显示,因此刷新提要并重新开始可能更合乎逻辑。
相比之下,如果您转到联系人页面 - 并因此被重新路由到 contacts.list
,这些条目可能已排序,无论是按字母顺序还是按添加日期。如果您滚动浏览并决定查看某个联系人,那么当您回来时顺序可能会相同,并且您可能不会有任何新联系人,因此最好从您离开的地方继续。这可以通过将联系人列表加载到父状态来完成,可能带有最后查看的联系人的 ID,以查看您在哪里。这方面的一个例子可能是面包屑元素,它指示潜在路径树中的路径。
如果你从一个状态移动到另一个状态,你就在节点之间创建了一条路径,比如说你 离开 create
到 进入 feed
,或者您 输入 contacts
然后 contacts.list
。如果您从 contacts.view
移动到 contacts.list
,您 保留 contacts
,因此该控制器将继续使用 - 它永远不会被销毁。
回溯历史与正常导航
不过,这里遗漏了一个重要的区别,即通过移动应用程序中的向后箭头或通过浏览器上的后退按钮向后移动之间的区别。这与单击按钮转到主页形成对比,因为它假定主页已在过去加载。
在许多移动应用程序中,导航被视为一种流程,尽可能避免使用大菜单。相反,更多的重点放在创建历史记录上,因此无论它们在树中的哪个位置,都可以通过向左滑动或始终单击相同的按钮来重新访问以前访问过的页面。此外,对于移动应用程序,无法假定可靠的网络连接,因此最好保持旧页面不变,而不是从服务器刷新和重新获取。这也是为什么像 Ionic 这样基于 AngularJS 的框架提供特定页面历史功能的原因。