首页 > web前端 > js教程 > 在Angularjs管理仅限客户状态

在Angularjs管理仅限客户状态

Christopher Nolan
发布: 2025-02-20 09:34:09
原创
724 人浏览过

Managing Client-Only State in AngularJS

在Angularjs管理仅限客户状态

钥匙要点

    AngularJ中的
  • 查看模型可以具有仅限客户端状态,例如“动画启动”和“动画”或“拖动”和“删除”。使用Angular的$ Resource Service创建和保存视图模型时,可以管理此状态。>
  • >将状态变化逻辑封装在一个地方,例如注射服务,可以简化代码并减少错误,尤其是对于具有多重消费者的应用程序。
  • >诸如功能包装之类的技术可用于保存和检索数据之前和之后进行不同或其他的事情。这可以增强$ Resource Service的功能。
  • >将视图模型提取到注射服务中可以帮助扩展应用程序,尤其是具有复杂,实时更新的应用程序。观看和过滤等技术可用于管理状态变化并改善应用程序API的合成性。
  • JavaScript框架(例如AngularJs)中的
  • >查看模型可能与服务器上的域模型不同 - 视图模型甚至不必在服务器上存在。因此,视图模型只能具有客户端状态,例如“动画开始”和“动画”或“拖动”和“掉落”。这篇文章使用Angular的$ Resource Service创建和保存视图模型时将集中于状态更改。
>对于$资源消费者来说实际上非常容易,例如一个控制器,以设置状态,如下所示。

这种方法对于包含单个消费者的应用程序很好。想象一下,对于多个消费者,容易复制此代码的无聊和错误!但是,如果我们可以封装状态在一个地方更改逻辑怎么办?

>
angular<span>.module('clientOnlyState.controllers')
</span>    <span>.controller('ArticleCtrl', function($scope, $resource, ArticleStates /* simple lookup */) {
</span>        <span>var Article = $resource('/article/:articleId', { articleId: '@id' });
</span>
        <span>var article = new Article({ id: 1, title: 'A title', author: 'M Godfrey' });
</span>        article<span>.state = ArticleStates.NONE; // "NONE"
</span>
        $scope<span>.article = article;
</span>
        $scope<span>.save = function() {
</span>            article<span>.state = ArticleStates.SAVING; // "SAVING"
</span>
            article<span>.$save(function success() {
</span>                article<span>.state = ArticleStates.SAVED; // "SAVED"
</span>            <span>});
</span>        <span>};
</span>    <span>});</span>
登录后复制
登录后复制
$ Resource Services

>让我们从将我们的文章资源推入注射服务中。当首次创建文章时,我们还将最微不足道的状态设置添加到无。

检索和保存怎么样?我们希望将文章作为$资源服务出现在消费者身上,因此它必须像一个人一样始终如一地工作。我在John Resig的出色著作《 JavaScript Ninja的秘密》中学到的一种技术在这里非常有用 - 功能包装。这是他的实现直接提升为可注射的角度服务。

>

angular<span>.module('clientOnlyState.services')
</span>    <span>.factory('Article', function($resource<span>, ArticleStates</span>) {
</span>
        <span>var Article = $resource('/article/:articleId', { articleId: '@id' });
</span>
        <span>// Consumers will think they're getting an Article instance, and eventually they are...
</span>        <span>return function(data) {
</span>            <span>var article = new Article(data);
</span>            article<span>.state = ArticleStates.NONE;
</span>            <span>return article;
</span>        <span>}
</span>    <span>});</span>
登录后复制
登录后复制
>这使我们能够包装保存并获取文章的方法,并在之前和之后做一些不同/其他的事情:

angular<span>.module('clientOnlyState.services')
</span>    <span>.factory('wrapMethod', function() {
</span>        <span>return function(object<span>, method, wrapper</span>) {
</span>            <span>var fn = object[method];
</span>
            <span>return object[method] = function() {
</span>                <span>return wrapper.apply(this, [fn.bind(this)].concat(
</span>                    <span>Array.prototype.slice.call(arguments))
</span>                <span>);
</span>            <span>};
</span>        <span>}
</span>    <span>});</span>
登录后复制
登录后复制
>我们的控制器由于此而开始变得更加倾斜,并且完全不知道如何设置状态。这很好,因为控制器也不应该在乎。

>

angular<span>.module('clientOnlyState.controllers')
</span>    <span>.controller('ArticleCtrl', function($scope, $resource, ArticleStates /* simple lookup */) {
</span>        <span>var Article = $resource('/article/:articleId', { articleId: '@id' });
</span>
        <span>var article = new Article({ id: 1, title: 'A title', author: 'M Godfrey' });
</span>        article<span>.state = ArticleStates.NONE; // "NONE"
</span>
        $scope<span>.article = article;
</span>
        $scope<span>.save = function() {
</span>            article<span>.state = ArticleStates.SAVING; // "SAVING"
</span>
            article<span>.$save(function success() {
</span>                article<span>.state = ArticleStates.SAVED; // "SAVED"
</span>            <span>});
</span>        <span>};
</span>    <span>});</span>
登录后复制
登录后复制

封装益处

>我们已经竭尽全力封装了控制器之外的状态变化,但是我们获得了什么好处?

>现在,我们的控制器可以利用通过旧状态通过的手表听众来设置消息。它也可以执行本地翻译,如下所示。

angular<span>.module('clientOnlyState.services')
</span>    <span>.factory('Article', function($resource<span>, ArticleStates</span>) {
</span>
        <span>var Article = $resource('/article/:articleId', { articleId: '@id' });
</span>
        <span>// Consumers will think they're getting an Article instance, and eventually they are...
</span>        <span>return function(data) {
</span>            <span>var article = new Article(data);
</span>            article<span>.state = ArticleStates.NONE;
</span>            <span>return article;
</span>        <span>}
</span>    <span>});</span>
登录后复制
登录后复制
考虑$ scopes,指令和过滤器构成应用程序的API。 HTML视图消耗此API。 API的合成性越大,重用的潜力就越大。过滤器可以改善新观看与旧观看的合成性吗?

通过滤镜组合,灵丹妙药?

>

>类似以下内容是我的想法。表达的每个部分都可以重复使用。

angular<span>.module('clientOnlyState.services')
</span>    <span>.factory('wrapMethod', function() {
</span>        <span>return function(object<span>, method, wrapper</span>) {
</span>            <span>var fn = object[method];
</span>
            <span>return object[method] = function() {
</span>                <span>return wrapper.apply(this, [fn.bind(this)].concat(
</span>                    <span>Array.prototype.slice.call(arguments))
</span>                <span>);
</span>            <span>};
</span>        <span>}
</span>    <span>});</span>
登录后复制
登录后复制
从Angular 1.3开始,过滤器可以使用$ stateful属性,但是由于Angular无法根据输入参数的值调用过滤器,因此强烈劝阻其使用。因此,我们将将状态参数传递给Limittotransition(以前的状态)并翻译(可用翻译)。

因此,我们需要对文章进行稍作修改:
angular<span>.module('clientOnlyState.services')
</span>    <span>.factory('Article', function($resource<span>, ArticleStates, wrapMethod</span>) {
</span>        <span>var Article = $resource('/article/:articleId', { articleId: '@id' });
</span>
        <span>wrapMethod(Article, 'get', function(original<span>, params</span>) {
</span>            <span>var article = original(params);
</span>
            article<span>.$promise.then(function(article) {
</span>                article<span>.state = ArticleStates.NONE;
</span>            <span>});
</span>
            <span>return article;
</span>        <span>});
</span>
        <span>// Consumers will actually call $save with optional params, success and error arguments
</span>        <span>// $save consolidates arguments and then calls our wrapper, additionally passing the Resource instance
</span>        <span>wrapMethod(Article, 'save', function(original<span>, params, article, success, error</span>) {
</span>            article<span>.state = ArticleStates.SAVING;
</span>
            <span>return original.call(this, params, article, function (article) {
</span>                article<span>.state = ArticleStates.SAVED;
</span>                success <span>&& success(article);
</span>            <span>}, function(article) {
</span>                article<span>.state = ArticleStates.ERROR;
</span>                error <span>&& error(article);
</span>            <span>});
</span>        <span>});
</span>
        <span>// $resource(...) returns a function that also has methods
</span>        <span>// As such we reference Article's own properties via extend
</span>        <span>// Which in the case of get and save are already wrapped functions
</span>        <span>return angular.extend(function(data) {
</span>            <span>var article = new Article(data);
</span>            article<span>.state = ArticleStates.NONE;
</span>            <span>return article;
</span>        <span>}, Article);
</span>    <span>});</span>
登录后复制
>

最终结果并不那么漂亮,但仍然非常强大:>
angular<span>.module('clientOnlyState.controllers')
</span>    <span>.controller('ArticleCtrl', function($scope<span>, Article</span>) {
</span>        <span>var article = new Article({ id: 1, title: 'A title', author: 'M Godfrey' });
</span>        
        <span>console.log(article.state); // "NONE"
</span>
        $scope<span>.article = article;
</span>
        $scope<span>.save = function() {
</span>            article<span>.$save({}, function success() {
</span>                <span>console.log(article.state); // "SAVED"
</span>            <span>}, function error() {
</span>                <span>console.log(article.state); // "ERROR"
</span>            <span>});
</span>        <span>};
</span>    <span>});</span>
登录后复制

我们的控制器再次变得更倾斜,尤其是如果您认为可以将翻译拉出到可注射的服务中:

angular<span>.module('clientOnlyState.controllers')
</span>    <span>.controller('ArticleCtrl', function($scope<span>, Article, ArticleStates</span>) {
</span>        <span>var article = new Article({ id: 1, title: 'A title', author: 'M Godfrey' });
</span>
        <span>var translations = {};
</span>        translations<span>[ArticleStates.SAVED] = 'Saved, oh yeah!';
</span>        translations<span>['default'] = '';
</span>
        $scope<span>.article = article;
</span>
        $scope<span>.save = function() {
</span>            article<span>.$save({});
</span>        <span>};
</span>
        $scope<span>.$watch('article.state', function(newState<span>, oldState</span>) {
</span>            <span>if (newState == ArticleStates.SAVED && oldState == ArticleStates.SAVING) {
</span>                $scope<span>.message = translations[newState];
</span>            <span>} else {
</span>                $scope<span>.message = translations['default'];
</span>            <span>}
</span>        <span>});
</span>    <span>});</span>
登录后复制

结论

<span><span><span><p</span>></span>{{article.state | limitToTransition:"SAVING":"SAVED" | translate}}<span><span></p</span>></span></span>
登录后复制
>将视图模型提取到注射服务中有助于我们扩展应用程序。这篇文章中给出的示例很简单。考虑一个允许货币对交易的应用程序(例如,英镑至USD,EUR到GBP等)。每个货币对代表一个产品。在这样的应用程序中,可能会有数百种产品,每种产品都会收到实时价格更新。价格更新可能高于当前价格。该应用程序的一部分可能会关心连续两次更高的价格,而另一部分可能关心刚刚降低的价格。能够观察这些价格变化状态极大地简化了应用程序的各个部分。

>我提出了一种基于旧值和新值观察的替代方法。两者都是完全可以接受的技术 - 实际上,当我开始研究这篇文章时,我想到的是我的想法。过滤是在完成后附近发现的潜在改进。

>我很想看看我提出的技术是否可以帮助您扩展Angular应用程序。所有反馈都将在评论中得到极大的收获!

>

在研究此帖子时创建的代码样本也可以在GitHub上找到。

>在Angularjs中管理客户状态的经常询问的问题

> $ state -provider在AngularJS中管理客户端状态的作用是什么?这是一项允许您为应用程序定义状态的服务。每个状态就整体UI和导航而言,对应于应用程序中的“位置”。 $ state -provider提供了路由不同视图的API。激活状态时,它可以通过Resolve属性解析一组数据。然后将这些数据注入控制器。>

>我如何在$ state -provider中使用resolve属性?用于在激活状态之前解决一组数据。然后将这些数据注入控制器。解析属性是包含键值对的对象。关键是要注入控制器的依赖项的名称,该值是返回依赖关系值的函数。

>在Angularjs中使用UI-Router进行状态管理有什么好处?它允许嵌套视图和多个命名视图,这在较大的应用程序中可能非常有用。它还提供了基于状态的路由,它比AngularJS中的基于默认路由的路由更灵活,更强大。

>我如何在gangularjs中的状态之间过渡?在AngularJS中使用$ state.go()方法。该方法将状态的名称作为其第一个参数,而参数的可选对象是其第二个参数。参数对象可用于将数据传递到要过渡到的状态。

我可以在没有状态管理工具的情况下使用AngularJS吗?但是,随着您的应用程序的复杂性增长,如果使用UI-Router这样的工具,管理状态可能会变得越来越困难。使用状态管理工具可以帮助维持应用程序用户界面的一致性和可预测性。

>

>在AngularJS中管理状态的一些共同挑战是什么?保持用户界面的一致性,跟踪应用程序状态的变化以及管理应用程序的行为。通过使用UI-Router等状态管理工具。

以上是在Angularjs管理仅限客户状态的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板