Angular ui-router 嵌套视图不会刷新 Angular 服务检索到的数据 [英] Angular ui-router nested views don't refresh data retrieved by Angular Services

查看:16
本文介绍了Angular ui-router 嵌套视图不会刷新 Angular 服务检索到的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个重要的 Angular SPA,它使用 ui-router 来管理多个视图,其中许多视图同时可见.我需要模型在控制器之间可见,所以我编写了服务,允许我让控制器拉下已更新的模型数据的新副本.

I have a nontrivial Angular SPA that uses ui-router to manage multiple views, many of which are visible at the same time. I need models to be visible across controllers, so I have services written that allow me to have controllers pull down fresh copies of model data that has been updated.

对于问题的长度,我提前道歉,但我会先说明问题,然后说明我为解决我确信 Angular 社区中的其他人一直在努力解决的问题所做的工作.

I apologize in advance for the length of the question, but I will state the problem then state what I have done to address issues I'm sure others in the Angular community have struggled with.

我相信我的问题是不了解控制器/视图的生命周期,因为我得到的行为是控制器在我第一次去那里时正确初始化,但之后似乎再也不会运行,即使我使用类似的东西导航到它$state.go("州名").

I believe my problem is not understanding the lifecycle of controllers / views, because I get behavior where a controller initializes correctly the first time I go there, but then seems to never run again, even when I navigate to it using something like $state.go("state name").

在一个视图(人为的示例)中,我显示了有关客户的信息摘要,而在另一个视图中,我允许用户更新该客户的更详细的个人资料.我希望用户在详细视图中编辑客户姓氏,并让摘要视图自动识别并显示更改.

In one view (contrived example), I show a summary of information about a customer, and in another view I allow a user to update that customer's more detailed profile. I want a user to edit, say, the customer last name in the detailed view, and have the summary view automatically recognize the change and display it.

我有一个 fiddle 显示 3 个视图和一个简单的密码更改服务.流程是这样的:

I have a fiddle that shows 3 views and a simple password changing Service. The flow goes like this:

  1. 您可以看到每个视图都已初始化并显示从服务中检索到的初始密码.所有视图都与 DataService 同步.
  2. 中间视图允许您输入新密码并更改存储在服务中的密码.控制台日志记录确认该服务会按照您的预期获取新密码.
  3. (奇怪的行为 #1)当 DataService 收到新密码时,我希望其他 2 个视图(顶部和底部)显示新密码.他们没有......他们仍然显示初始密码.
  4. 有一个按钮允许用户通过 $state.go("state name")(原始状态的子状态)转到另一个 state还检索密码并显示它.这是第一次(参见#5).现在顶部视图显示过期密码,中间视图显示新密码,底部视图也显示新密码.这看起来很正常,因为在 DataService 包含新密码值之后调用了新视图.
  5. (奇怪的行为 #2)如果我在中间视图中单击返回并再次更改密码,然后单击按钮再次更改状态,底部视图(在步骤 #4 中更新得很好)不再更新其副本的密码.现在所有 3 个视图都显示了不同的密码,即使我使用单个服务在控制器之间传递值,正如您在寻找 Angular 最佳实践的任何地方所建议的那样.
  1. You can see each view gets initialized and displays the initial password retrieved from the service. All views are in sync with the DataService.
  2. The middle view allows you to enter a new password and change the one stored in the service. Console logging confirms that the service picks up the new password just like you would expect.
  3. (odd behavior #1) When the DataService receives the new password, I would expect the other 2 views (top and bottom) to display the new one. They don't... they still display the initial password.
  4. There is a button to allow a user to go to another state via $state.go("state name") (a child state of the original) which also retrieves the password and displays it. This works the first time (see #5). Now the top view shows the outdated password, the middle view shows the new one, and the bottom one shows the new one as well. This seems normal, since the new view is invoked after the DataService contains a new password value.
  5. (odd behavior #2) If I click back in the middle view and change the password again, and click the button to change states again, the bottom view (which updated just fine in step #4) no longer updates its copy of the password. Now all 3 views show different passwords, even though I am using a single service to pass values between controllers as suggested pretty much everywhere you look for Angular best practices.

一些可能的解决方案:

  • Tim Kindberg 有一个很棒的幻灯片here 似乎推荐使用 ui-router 的 state heirarchy 在需要从其他视图中获取值的视图之间传递"数据.对于较小规模的应用程序,我想我会解决这个问题,但我希望我们的应用程序有 30 多个视图来显示来自 100 多个 REST 端点的数据.我对维护一个所有数据都由复杂的继承树共享的应用程序感到不舒服.尤其是使用 0.2.8 版本的路由框架.
  • 我可以使用事件让控制器监听数据模型的变化.这实际上效果很好.为了解决性能问题,我使用 $rootScope.emit()这里.使用这种方法,我不太关心事件性能,而是将这个巨大的应用程序与一堆事件侦听器连接在一起.有一个关于使用角度事件连接大型应用程序是否明智的问题 这里.
  • 对 DataService 中的值使用 $watch?我没有尝试过,但出于性能原因,我很犹豫是否将这种大小的应用程序连接到数百个 $watches 上.
  • 第三方库,例如 bacon.js(或其他十几个库中的任何一个)这可能会简化事件意大利面,或者创建我的控制器可以观看的可观察模型,而不会出现 $digestageddon 的风险.当然,如果有一种使用 Angular 处理我的问题的简洁方法,我不希望使用 3rd 方依赖项来混淆应用程序.
  • 让控制器通过引用实际引用 .service 模块的东西,因此我不必依赖大量的事件连接、复杂的状态层次结构、第 3 方库或为应用程序植入数百个$watches 然后启动 $digests 来更新控制器对 Angular 服务的引用?
  • 一些解决方案依赖于经过时间考验的 OO 和设计模式,而不是版本以 0.* 开头的第 3 方库或框架.
  • Tim Kindberg has an excellent slideshow here that seems to recommend using ui-router's state heirarchy to "pass" data among views that need to pick up values from other views. For a smaller-scale app I think I would settle on this, but I expect our application to have 30+ views displaying data from over 100 REST endpoints. I don't feel comfortable maintaining an application where all the data is being shared by a complex inheiritance tree. Especially using a routing framework that is at version 0.2.8.
  • I can use events to have controllers listen for changes in the data model. This actually works well. To accommodate performance concerns, I am using $rootScope.emit() and a $scope.$onRootScope('event name') decorator I found on here. With this approach I am less concerned about event performance than I am about wiring this huge app with a bunch of event listeners tying everything together. There is a question about the wisdom of wiring a large app using angular events here.
  • Using $watch on the value in the DataService? I have not tried this but I am hesitant to hinge an app this size on hundreds of $watches for performances reasons.
  • A third-party library like bacon.js (or any of a dozen others) that may simplify the event spaghetti, or create observable models that my controllers can watch without the risk of $digestageddon. Of course, if there is a concise way to handle my issue using Angular, I'd prefer not to muddy the app with 3rd party dependencies.
  • Something that lets controllers actually reference .service modules by reference, so I don't have to depend on tons of event wiring, complex state hierarchies, 3rd party libraries, or seeding the app with hundreds of $watches and then kicking off $digests to update controllers' references to Angular services?
  • Some solution that relies on time-tested OO and design patterns and not a 3rd-party library or framework that has a version that starts with 0.*.

在此先感谢...感谢您的帮助!

Thanks in advance... I appreciate the help!

推荐答案

这不是ui.router的问题.如果您打算让您的模型(您的数据服务)成为单一的事实来源,则必须避免破坏它.. err.. 对它的引用.在您的情况下,将原始(字符串)直接分配给范围,而不是对其的引用.也就是说……

This is no problem of ui.router. If you intend for your model (your data service) to be a single source of truth, you have to refrain from destroying it.. err.. the reference to it that is. And in your case, assigning a primitve (a string) directly to the scope, instead of a reference to it. In other words...

var password = {pw:'initial value'};

然后只在以后设置/绑定

and then later setting/binding only on

password.pw = newpassword

{{password.pw}}

这是一个小提琴.这里还有一个关于范围的简短阅读,它还包括一个角度聚会的视频,其中 Misko 谈到在你的模型中总是有一个点"link 以及 $scope 如何成为展示您的模型的地方,而不是您的模型.(也不是分配像 password = 'initial value' 这样的原语的地方)

Heres a fiddle. And also here is a short little read on scopes, It also includes a video of an angular meetup where Misko talks about "always have(ing) a dot in your model" link and how the $scope is a place to expose your model, not be your model. (aka not a place to assign primitives like password = 'initial value')

希望这会有所帮助!

这篇关于Angular ui-router 嵌套视图不会刷新 Angular 服务检索到的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆