使用参数缓存URL视图/状态

时间:2014-10-27 15:43:07

标签: javascript angularjs angular-ui-router angular-routing

我正在使用Cordova和AngularJS制作移动应用。目前我已经安装了ui-router用于路由,但是我可以选择其他任何路由选择。

我的愿望:我想缓存某些与参数绑定的视图。换句话说,我想缓存路径(或页面)。

示例情况:假设我们看到一些信息中心页面,点击一些重定向到路径book/2的书籍封面。此路径首次加载到应用程序中。路由器从HomeController重定向到BooksController(无论名称如何)。现在,BooksController加载了给定$stateParams的数据(图书ID = 2),并创建了包含所选图书信息的视图。

在这种情况下我想要的是什么:

  1. 我回到仪表板页面 - 它已经加载(缓存?)
  2. 我再次选择了第二本书
  3. 控制器或路由器已注意到已加载有关此图书的数据
  4. 视图未被重新创建,而是从缓存中提取
  5. 实际上,最好根据路径缓存我访问的所有内容。预加载也很酷。

    原因:表现。当我打开一些书籍列表时,我希望它能够快速显示。每次创建视图时,页面更改的动画看起来很糟糕(它不是很平滑)。

    任何帮助都将不胜感激。

    编辑:

    首先,由于我认为这是许多移动HTML应用程序编程人员的常见问题,我想准确一些信息:

    1. 我不是在寻找黑客,而是一个明确的解决方案如果可能。
    2. 视图中的数据使用AngularJS,所以是的, 之类的内容有ng-bindng-repeat等等。
    3. 数据 DOM元素需要
    4. 缓存。据我所知,浏览器的布局操作并不像重新创建整个DOM树那样昂贵。重画不是我们可以省略的。
    5. 拥有独立的控制器是很自然的事情。因为我可以在没有它的情况下离开,所以我无法想象它是如何工作的。
    6. 我有一些半解决方案,但我会严格要求。

      解决方案1。

      将所有视图放入一个文件(我可以使用gulp builder)并使用ng-show。这是最简单的解决方案,我不相信任何知道AngularJS的人都不会考虑它。

      精彩技巧(来自@DmitriZaitsev)是创建一个帮助函数,根据当前位置路径显示/隐藏元素。

      优点:

      1. 很容易。
      2. 预加载功能。
      3. 缺点:

        1. 所有视图都必须位于单个文件中。不要问为什么不方便。
        2. 由于这一切都与移动设备有关,有时我想“清除”内存。我能想到的唯一方法是从DOM中删除这些孩子。肮脏但还可以。
        3. 我无法同时缓存/预订/ 2和/ book / 3。我必须在每个使用参数绑定的视图的模板之上动态创建DOM子项。
        4. 解决方案2.

          使用来自ui-router-extras的粘性状态和未来状态非常棒。

          优点:

          1. 分开观点。
          2. 非常明确的用法,非常简单,因为它只是ui-router的插件。
          3. 可以创建动态子状态。因此,可以缓存book1book2,但我不确定book/1book/2
          4. 缺点:

            1. 同样,我不确定,但我没有找到缓存 / tuple (view, parameters)的示例。除此之外它看起来很酷。

3 个答案:

答案 0 :(得分:11)

这正是我必须为我的网站33hotels.com解决的问题。您可以检查它并使用选项卡"过滤"和"过滤列表" (对应不同的路由),看到视图立即更新,没有任何延迟!

我是怎么做到的?这个想法非常简单 - 摆脱路由器!

为什么呢?由于路由器的工作方式是重新编译视图每次路由更改。是的,Angular会缓存 Template ,但不会缓存填充了数据的已编译View。即使数据不变!结果,当我过去使用路由器时,开关总是感觉迟钝且无反应。每当我注意到令人讨厌的延迟时,它只是一小部分但仍然明显。

现在我使用的解决方案?不要重新编辑你的观点!始终将它们放在DOM中!然后使用ng-hide / ng-show隐藏/显示它们,具体取决于路线:

<div ng-show="routeIs('/dashboard')">
    <-- Your template for Dashboard -->
</div>

<div ng-show="routeIs('/book')">
    <-- Your template for Book -->
</div>

然后在routeIs(string)内创建一个函数Controller来测试$location.path()是否与string匹配,或者在我使用string时以/book/2开头。这样我仍然可以查看$scope.routeBegins = function () { return _.some(arguments, function (string) { return 0 === $location.path().indexOf(string); }); }; 等所有广告的视图。这是我正在使用的功能:

{{1}}

所以不需要聪明地使用缓存 - 只需将其保存在DOM中即可。它将为您缓存您的视图!

最好的部分是 - 每当您的数据发生变化时,Angular会立即更新您DOM中的所有视图,甚至是隐藏的视图!

为什么这很棒?因为,作为用户,我不必等待所有解析和编译,此刻我想看到结果。我想点击标签,立即查看我的结果!为什么网站会等我点击它然后然后开始所有的重新编译,因为我在等待?特别是在我的计算机闲置之前,这可以很容易地完成。

有任何缺点吗?我唯一能想到的是用更多DOM元素加载内存。但是,我的视图的实际字节大小可以忽略不计,例如,使用所有JS,CSS和图像。

另一个可能但可以避免的缺点是隐藏视图的重新编译成本。这是您可以变得聪明并避免计算繁重的部分,具体取决于当前路线。 此外,您不是要重新编译整个视图,只是受数据更改影响的部分,这也会降低计算成本。

我发现每个人都在使用路线并且似乎完全没有意识到(或无知)这个问题,我觉得非常了不起。

答案 1 :(得分:1)

1)关于app(views)中的静态页面,angular负责加载它们。

例如:对于您的信息中心页面,您无需担心缓存页面,因为angular会处理它。 Angular将仅加载仪表板视图一次以及对仪表板视图的所有下一个请求,angular将仅显示视图(不加载文件以供查看),如果它是一个静态视图,而没有任何数据由ajax调用加载。 / p>

2)如果您的仪表板本身通过ajax加载图书清单(或类似数据),那么您可以告诉您的控制器只加载一次数据并将其存储到本地存储中,并且对仪表板页面的后续请求只能加载来自localStorage的数据。

3)当BooksController将数据加载到视图中时,可以使用类似的方法。如果先前已经对特定图书的请求进行了检查,则可以签入BooksController,如果没有,则可以将其存储到localstorage或数据库。如果以前请求了数据,那么您可以从存储中加载相同的数据,而无需向服务器发出请求。

示例情况:

说用户请求book1,然后

  
      
  1. 您的控制器,即BooksController检查之前是否请求过相同的数据,
  2.   
  3. 如果没有,您可以通过服务器的ajax调用加载数据,并将其保存到本地存储。
  4.   
  5. 如果在加载存储在localstorage或数据库中的数据之前加载了它。
  6.   

答案 2 :(得分:1)

如果你正在使用ui.router,那么你应该看一下ui.router extras,特别是粘滞状态模块。这允许您缓存状态“树”(包括渲染视图),因此不必在状态更改时编译或重新呈现它们。

http://christopherthielen.github.io/ui-router-extras/

这是一个演示:

http://christopherthielen.github.io/ui-router-extras/example/sticky/#/