如何自动注入状态参数 [英] How to inject state parameter automatically

查看:22
本文介绍了如何自动注入状态参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘要

我在我的项目中使用 angular + ui-router,我有大量的嵌套状态和不同的视图,这些视图又包含大量不同的输入,用户逐步填充这些输入.

问题

有时用户需要位于上一步的附加信息,而浏览器会返回".按钮可以帮助用户偷看数据,但是一旦用户按下它,由于状态转换,他已经输入的信息就会丢失,这显然是一件坏事.

战略

为了克服所描述的问题,我有以下计划:

  1. 关联每个用户的导航"(猜这是一个适当的术语)带有随机 ID
  2. 为了防止作用域继承和序列化问题,不要将视图模型放入 $scope 使用普通的 javascript 对象,该对象将存储绑定到 UI 的立即值.
  3. 添加观察者以查找该存储对象"的变化
  4. 一旦发现变化,就序列化对象并持久化

说明

为什么我们需要在 URL 中使用随机参数?

我们不想将所有数据都存储在 URL 中,因为可能有相当多的数据无法放入 URL.因此,为了保证 URL 不会中断,我们只将小的随机 GUID/UUID 放入其中,以便稍后获取与当前导航"相关联的数据.通过这个随机 GUID/UUID.

存储

有多种可用的存储方案:LocalStorageIndexedDBWebSQLSession Storage、随便你说,但由于它们的交叉表、跨浏览器、特定于浏览器的特性,很难操纵和管理进入存储的所有数据.实现将有问题/可能需要服务器端支持.

因此,对于这种情况,最优雅的存储策略是将数据存储在特殊的 window.name 变量中,该变量能够在请求之间存储数据.因此,在您关闭标签之前,数据是安全的.

问题

代表上面写的所有内容,我有一个名为view"的根视图.具有状态参数 id(这是随机 GUID/UUID)

$stateProvider.state('view', {url: '/view/{id}',控制器:'视图',templateUrl: 'views/view.html'});

所有其他视图都从这个视图派生出来,有没有办法让 ui-sref 指令自动注入一个随机 GUID/UUID 到我的 id 状态参数中根视图,而不是每次都写 ui-sref 就像:

我想要类似的东西:

AOP 和装饰器模式就是答案.可以在此处找到全面的描述:

实验:装饰指令,Jesus Rodriguez

可以观察到如下所述的类似解决方案:

更改 ui.router 中 $state.go() 的默认行为以默认重新加载

这将如何运作?有一个链接到 工作示例

在这种情况下,我们不解决随机 GUID 来自哪个来源.让我们在运行时使用它:

var guidFromSomeSource = '70F81249-2487-47B8-9ADF-603F796FF999';

现在,我们可以像这样注入一个装饰器:

角度.module('MyApp').config(功能($提供){$provide.decorator('$state', function ($delegate) {//让我们在本地使用 'state' 名称var state = $delegate;//让我们用新函数扩展这个对象//'baseGo',实际上会保留引用//到原来的 'go' 函数state.baseGo = state.go;//我们新的go"装饰来了var go = function (to, params, options) {参数 = 参数 ||{};//仅在缺少 'id' 的情况下//附加我们的随机/常量GUID"如果(angular.isUndefined(params.id)){params.id = guidFromSomeSource;}//将处理返回到 'baseGo' - 原始this.baseGo(to, params, options);};//分配新的go",现在装饰旧的go"state.go = 去;返回 $delegate;});})

代码应该是不言自明的,在操作中检查它这里

Abstract

Hi, I'm using angular + ui-router in my project, I have huge amount of nested states and different views that in turn contain huge amount of different inputs, a user fills these inputs incrementally step by step.

The problem

Sometimes users require additional info that is located on the previous step, and browsers "back" button helps the user to sneak peek into that data, but as soon as the user presses it, the info he already entered is lost due to state transition, which is obviously a bad thing.

Strategy

In order to overcome described problem I have the following plan:

  1. Associate each user's "navigation" (guess this is a proper term) with a random id
  2. To prevent scope-inheritance-and-serialization issues, instead of putting viewmodel into $scope use ordinary javascript object that will be storing immediate values that are bound to UI.
  3. Add watcher to look for changes on that "storage object"
  4. As soon as the change spotted, serialize the object and persist it

Explanations

Why do we need a random parameter in URL?

We don't want to store all data in URL, since there might be quite some amount of data that wont fit into URL. So in order to provide the guarantees the URL won't break, we put only small random GUID/UUID into it that later allows obtaining the data associated with current "navigation" by this random GUID/UUID.

The storage

There are multitude of storage scenarios available out there: LocalStorage, IndexedDB, WebSQL, Session Storage, you name it, but due to their cross-tab, cross-browser, browser-specific nature it would be hard to manipulate and manage all of the data that gets into the storage. The implementation will be buggy / might require server-side support.

So the most elegant storage strategy for this scenario would be storing data in special window.name variable which is capable of storing data in-between requests. So the data is safe until you close your tab.

The Question

On behalf of everything written above, I have the root view called "view" that has a state parameter id (this is the random GUID/UUID)

$stateProvider.state('view', {
    url: '/view/{id}',
    controller: 'view',
    templateUrl: 'views/view.html'
});

All of the other views derive from this view, is there way to make ui-sref directive to automatically inject a random GUID/UUID into id state parameter of my root view, instead of writing each time ui-sref's like:

<a ui-sref="view({id:guid()}).someNestedView({someNestedParam: getParam()})"

I would like to have something like:

<a ui-sref="view.someNestedView({someNestedParam: getParam()})"

解决方案

The AOP and Decorator pattern are the answer. The comprehensive description could be found here:

Experiment: Decorating Directives by Jesus Rodriguez

Similar solution as described below, could be observed:

Changing the default behavior of $state.go() in ui.router to reload by default

How that would work? There is a link to working example

In this case, we do not solve from which source the random GUID comes from. Let's just have it in runtime:

var guidFromSomeSource = '70F81249-2487-47B8-9ADF-603F796FF999';

Now, we can inject an Decorator like this:

angular
.module('MyApp')
.config(function ($provide) {
    $provide.decorator('$state', function ($delegate) {

        // let's locally use 'state' name
        var state = $delegate;

        // let's extend this object with new function 
        // 'baseGo', which in fact, will keep the reference
        // to the original 'go' function
        state.baseGo = state.go;

        // here comes our new 'go' decoration
        var go = function (to, params, options) {
            params = params || {};

            // only in case of missing 'id'
            // append our random/constant 'GUID'
            if (angular.isUndefined(params.id)) {

                params.id  = guidFromSomeSource;
            }

            // return processing to the 'baseGo' - original
            this.baseGo(to, params, options);
        };

        // assign new 'go', right now decorating the old 'go'
        state.go = go;

        return $delegate;
    });        
})

Code should be self explanatory, check it in action here

这篇关于如何自动注入状态参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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