使用参数缓存 URL 视图/状态 [英] Caching URL view/state with parameters

查看:27
本文介绍了使用参数缓存 URL 视图/状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Cordova 和 AngularJS 制作一个移动应用程序.目前我已经安装了用于路由的 ui-router,但我愿意接受任何其他路由选择.

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

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

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

  1. 我返回仪表板页面 - 它已加载(缓存?)
  2. 我再次选择第 2 本书
  3. 控制器或路由器注意到有关这本书的数据已经加载
  4. 视图没有被重新创建,而是从缓存中获取

实际上,最好根据路径缓存我访问的所有内容.预加载也很酷.

原因:性能.当我打开一些书单时,我希望它快速显示.每次创建视图时,页面变化的动画看起来很糟糕(不流畅).

任何帮助将不胜感激.

首先,由于我相信这是许多移动 HTML 应用程序程序员的常见问题,因此我想提供一些信息:

  1. 我不是在寻找黑客,而是在寻找明确的解决方案如果可能.
  2. 视图中的数据使用 AngularJS,所以是的,有 之类的东西,例如 ng-bindng-repeat 等等.
  3. 缓存数据DOM元素都需要.据我所知,浏览器的布局操作并不像重新创建整个 DOM 树那么昂贵.重绘不是我们可以省略的.
  4. 拥有单独的控制器是很自然的事情.因为我可以离开它,所以我无法想象它会如何运作.

我有一些半解决方案,但我会严格要求.

解决方案 1.

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

一个不错的技巧(来自@DmitriZaitsev)是创建一个辅助函数来根据当前位置路径显示/隐藏元素.

优点:

  1. 很简单.
  2. 某种预加载功能.

缺点:

  1. 所有视图都必须在一个文件中.不要问为什么不方便.
  2. 因为这都是关于移动设备的,所以有时我想清除"内存.我能想到的唯一方法是从 DOM 中删除这些孩子.脏但还好.
  3. 我无法轻松地同时缓存/book/2 和/book/3.我必须为每个绑定参数的视图在一些模板之上动态创建 DOM 子项.

解决方案 2.

使用来自 ui-router-extras 的粘性状态和未来状态,这很棒.

优点:

  1. 单独的视图.
  2. 非常清晰的用法,非常简单,因为它只是一个ui-router的插件.
  3. 可以创建动态子状态.所以可以缓存 book1, book2 但我不确定 book/1book/2

缺点:

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

解决方案

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

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

为什么?因为路由器的工作方式是重新编译视图,每次路由更改.是的,Angular 会缓存 Template 但不会缓存填充数据的编译视图.即使数据不改变!结果,我以前用Router的时候,总是感觉switch不灵,反应迟钝.每次我都能注意到烦人的延迟,它只是几分之一秒,但仍然很明显.

现在我使用的解决方案是什么?不要重新编译您的视图!始终将它们保存在您的 DOM 中!然后使用 ng-hide/ng-show 根据路线隐藏/显示它们:

<-- 您的仪表板模板-->

<div ng-show="routeIs('/book')"><-- 您的图书模板-->

然后在 Controller 中创建一个函数 routeIs(string) 来测试 $location.path() 是否匹配 string,或者在我使用它时以 string 开头.这样我仍然可以得到像 /book/2 这样的所有路径的视图.这是我正在使用的功能:

$scope.routeBegins = function () {返回 _.some(参数,函数(字符串){返回 0 === $location.path().indexOf(string);});};

因此无需对缓存进行智能处理 - 只需将其保存在 DOM 中即可.它将为您缓存您的视图!

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

为什么这么棒?因为,作为用户,我不需要在我想看到结果的那一刻等待所有的解析和编译.我想单击选项卡并立即查看我的结果!为什么网站要等待我点击它,然后然后在我等待时开始所有的重新编译?尤其是在以前可以轻松完成的情况下,在我的计算机空闲时.

有什么缺点吗?我能想到的唯一真正的方法是用更多的 DOM 元素加载内存.但是,我的视图的实际字节大小可以忽略不计,例如比较包含所有 JS、CSS 和图像.

另一个可能但可以避免的缺点是隐藏视图的重新编译成本.这是您可以变得聪明并根据当前路线避免计算量大的部分的地方.此外,您无需重新编译整个 View,只需重新编译受数据更改影响的部分,这也降低了计算成本.

我发现每个人都在使用 Routes 并且似乎完全不知道(或无知)这个问题是非常了不起的.

I'm making a mobile app using Cordova and AngularJS. Currently I have installed ui-router for routing but I'm open to any other alternative for routing.

My desire: I want to cache certain views bound with parameters. In other words I want to cache paths (or pages).

Example situation: let's say that we see some dashboard page, click on some book cover which redirects to the path book/2. This path is being loaded for the first time into app. Router redirects from HomeController to BooksController (whatever the name). Now the BooksController loads data for given $stateParams (book id = 2) and creates view filled with info about chosen book.

What I want in this situation:

  1. I go back to the dashboard page - it is already loaded (cached?)
  2. I choose book #2 again
  3. Controller or router notices that data about this book is already loaded
  4. The view isn't being recreated, instead it's being fetched from cache

Actually, it would be best to cache everything what I visit based on path. Preloading would be cool too.

Reason: performance. When I open some list of books then I want it to show fast. When view is being created every time, then animation of page change looks awful (it's not smooth).

Any help would be appreciated.

EDIT:

First of all, since I believe it's a common problem for many mobile HTML app programmers, I'd like to precise some information:

  1. I'm not looking for hacks but a clear solution if possible.
  2. Data in the views uses AngularJS, so YES, there are things like ng-bind, ng-repeat and so on.
  3. Caching is needed for both data and DOM elements. As far as I know, browser's layout operation is not as expensive as recreating whole DOM tree. And repaint is not what we can omit.
  4. Having separate controllers is a natural thing. Since I could leave without it I cannot imagine how it would work anyway.

I've got some semi-solutions but I'm gonna be strict about my desire.

Solution 1.

Put all views into one file (I may do it using gulp builder) and use ng-show. That's the simplest solution and I don't believe that anyone knowing AngularJS would not think about it.

A nice trick (from @DmitriZaitsev) is to create a helper function to show/hide element based on current location path.

Advantages:

  1. It's easy.
  2. KIND OF preload feature.

Disadvantages:

  1. all views have to be in a single file. Don't ask why it's not convenient.
  2. Since it's all about mobile devices, sometimes I'd like to "clear" memory. The only way I can think of is to remove those children from DOM. Dirty but ok.
  3. I cannot easily cache /book/2 and /book/3 at the same time. I would have to dynamically create DOM children on top of some templates for each view bound with parameters.

Solution 2.

Use Sticky States AND Future States from ui-router-extras which is awesome.

Advantages:

  1. Separated views.
  2. Very clear usage, very simple since it's just a plugin for ui-router.
  3. Can create dynamic substates. So it would be possible to cache book1, book2 but I'm not sure about book/1 and book/2

Disadvantages:

  1. Again, I'm not sure but I didn't found an example with caching a pair/tuple (view, parameters). Other than that it looks cool.

解决方案

This is precisely the problem I had to solve for my site 33hotels.com. You can check it and play with the tabs "Filter" and "Filter List" (corresponding to different Routes), and see that the View is updated instantly without any delay!

How did I do it? The idea is surprisingly simple - get rid of the Router!

Why? Because the way the Router works is it re-compiles the View upon every single Route change. Yes, Angular does cache the Template but not the compiled View populated with data. Even if data do not change! As the result, when I used the Router in the past, the switch always felt sluggish and non-reactive. Every time I could notice annoying delay, it was a fraction of second but still noticeable.

Now the solution I used? Don't re-compile your Views! Keep them inside your DOM at all times! Then use ng-hide/ng-show to hide/show them depending on the routes:

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

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

Then create a function routeIs(string) inside your Controller to test if $location.path() matches string, or begins with string as I am using it. That way I still get my View for all pathes like /book/2. Here is the function I am using:

$scope.routeBegins = function () {
    return _.some(arguments, function (string) {
           return 0 === $location.path().indexOf(string);               
    });
};            

So no need to be smart with caching - just keep it in the DOM. It will cache your Views for you!

And the best part is - whenever your data is changed, Angular will instantly update all the Views inside your DOM, even the hidden ones!

Why is this awesome? Because, as user, I don't have to wait for all the parsing and compiling at the moment I want to see the result. I want to click the tab and see my results immediately! Why should the site wait for me to click it and then begin all the re-compiling as I am waiting? Especially when this could be easily done before, during the time my computer is idle.

Is there any downside? The only real one I can think of is loading memory with more DOM elements. However, this actual byte size of my views is negligible, comparing e.g. with all JS, CSS and images.

Another possible but avoidable downside is the re-compilation cost of the hidden views. This is where you can get smart and avoid computation-heavy parts depending on the current routes. Also, you are not re-compiling the whole View, just the parts affected by data changes, which also lowers computational cost.

I find it quite remarkable that everyone is using Routes and seems to be completely unaware (or ignorant) of this problem.

这篇关于使用参数缓存 URL 视图/状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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