首頁 > 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
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板