如何防止另一个$ state更新时刷新特定的$ state [英] How to prevent specific $state from refreshing when another $state updates

查看:94
本文介绍了如何防止另一个$ state更新时刷新特定的$ state的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

https://plnkr.co/edit/bOZW1a9u62W1QA6cYjYj?p=preview

预期

登录所有的$ states初始化后,然后单击"Ticker"按钮后,唯一应重新初始化的$ states是 ticker 标签 >和 social ,但没有 feed .

结果

登录之后,所有$ state均初始化,然后在单击"Ticker"按钮后,所有$ states重新初始化. 提要不应该.

应如何设计仪表板和提要模块以防止这种情况?目前,我在dashboard.html内有<feed-module></feed-module>.它和仪表板是否应该在另一个中间状态/组件中进一步分开?也许是container.component?

完整代码

// Feed module
////////////////////////////////////////////////////////////////////////////////
var feed = angular.module('feed', ['ui.router'])

feed.config(function($stateProvider) {
  
  const feed = {
    name: 'feed',
    url: '/feed',
    templateUrl: '<em>Feed items go here.</em>'
  }
  
  $stateProvider.state(feed);
  
})

feed.component('feedModule', {
  templateUrl: 'feed-module-template.html',
  controller: function($scope, $state) {
    console.log('Feed init (only once)', $state.params);
  }
})

// RouterApp module
////////////////////////////////////////////////////////////////////////////////
var routerApp = angular.module('routerApp', ['ui.router', 'feed']);

routerApp.config(function($stateProvider, $urlRouterProvider) {
    
    $urlRouterProvider.otherwise('/login');

    const login = {
      name: 'login',
      url: '/login',
      templateUrl: 'login.html',
      bindToController: true,
      controllerAs: 'l',
      controller: function($state) {
        this.login = function() {
          $state.go('dashboard', {});
        }
      }
    }

    const dashboard = {
      name: 'dashboard',
      url: '/dashboard',
      params: {
        ticker: {},
        tags: {}
      },
      views: {
        '' : {
          templateUrl: 'dashboard.html',
        },
        'tickers@dashboard': {
          templateUrl: 'tickers-module-template.html',
          controller: function($scope, $state) {
            console.log('Tickers init', $state.params);
        
            $scope.tickers = [
              { id: 1, ticker: 'AAPL' },
              { id: 2, ticker: 'GOOG' },
              { id: 3, ticker: 'TWTR' }
            ];
            
            $scope.clickTicker = function(ticker) {
              console.log(' ')
              console.log('Ticker clicked!')
              $state.go('dashboard', { ticker: ticker });
            }
          }
        },
        'tags@dashboard' : {
          templateUrl: 'tags-module-template.html',
          controller: function($scope, $state) {
            const tags_model = [
              {
                ticker: 'AAPL',
                tags : [{ id: 1, term: 'iPhone 7' }, { id: 2, term: 'iPhone 8' }, { id: 3, term: 'Tim Cook' }]
              },
              {
                ticker: 'GOOG',
                tags : [{ id: 4, term: 'Pixel' }, { id: 5, term: 'Pixel XL' }, { id: 6, term: 'Chrome Book' }]
              },
              {
                ticker: 'TWTR',
                tags : [{ id: 7, term: 'tweet' }, { id: 8, term: 'retweet' }, { id: 9, term: 'moments' }]
              }
            ];
            
            function matchTags(ticker, model) {
              return model.filter(function(obj){
                if (obj.ticker === ticker) { return obj; }
              });
            }
            
            $scope.tags_model = matchTags($state.params.ticker.ticker, tags_model)[0];
            
            $scope.clickTag = function(tag) {
              $state.go('tags', { tag: tag });
            }
            
            console.log('Tags init', $state.params);
            // console.log(' Tags model', tags_model);
          }
        },
        'social@dashboard' : {
          templateUrl: 'social-module-template.html', 
          controller: function($state) {
            console.log('Social init', $state.params);
          }
        }
      }
    }

    $stateProvider
      .state(login)
      .state(dashboard);
});

这样的架构会起作用吗?基本上login是否会导航到container状态,其中将包含2个组件(dashboardfeed),每个组件都有自己的内部状态?

解决方案

我可以根据您来自哪个州来解决此问题.基于您只希望在加载仪表板时一次"加载提要的事实,我正在检查先前状态的名称,如果不是仪表板,则仅继续执行其余的状态.控制器代码.这是矮人.请注意,如果添加了更多状态,并且如果其他人有更好的方法,则这不是可扩展的方法,我真的很乐意看到它.

我如下更改了控制器代码:

feed.component('feedModule', {
  templateUrl: 'feed-module-template.html',
  controller: function($scope, $state) {
    var previousState = $state.params.previousState.name;
    if(previousState !== 'dashboard') {
      console.log('Feed init (only once)', $state.params); //do whatever u want here
    }
  }
});

我将以前的状态作为参数传递给其他状态,例如:

controller: function($state) {
  this.login = function() {
    $state.go('dashboard', {previousState : { name : $state.current.name }})
  }
}

查看完整的监听器此处看看这是否对您有帮助!/p>

https://plnkr.co/edit/bOZW1a9u62W1QA6cYjYj?p=preview

Expected

After Login all $states initialize, then after clicking a Ticker button, the only $states that should re-init are ticker, tags and social, but not feed.

Results

After Login all $states initialize, then after clicking a Ticker button all $states re-initialized. The feed should not.

How should the dashboard and feed module be architected to prevent this? At the moment I have the <feed-module></feed-module> inside the dashboard.html. Should it and the dashboard be further separated out in another in-between state/component? A container.component perhaps?

Full code

// Feed module
////////////////////////////////////////////////////////////////////////////////
var feed = angular.module('feed', ['ui.router'])

feed.config(function($stateProvider) {
  
  const feed = {
    name: 'feed',
    url: '/feed',
    templateUrl: '<em>Feed items go here.</em>'
  }
  
  $stateProvider.state(feed);
  
})

feed.component('feedModule', {
  templateUrl: 'feed-module-template.html',
  controller: function($scope, $state) {
    console.log('Feed init (only once)', $state.params);
  }
})

// RouterApp module
////////////////////////////////////////////////////////////////////////////////
var routerApp = angular.module('routerApp', ['ui.router', 'feed']);

routerApp.config(function($stateProvider, $urlRouterProvider) {
    
    $urlRouterProvider.otherwise('/login');

    const login = {
      name: 'login',
      url: '/login',
      templateUrl: 'login.html',
      bindToController: true,
      controllerAs: 'l',
      controller: function($state) {
        this.login = function() {
          $state.go('dashboard', {});
        }
      }
    }

    const dashboard = {
      name: 'dashboard',
      url: '/dashboard',
      params: {
        ticker: {},
        tags: {}
      },
      views: {
        '' : {
          templateUrl: 'dashboard.html',
        },
        'tickers@dashboard': {
          templateUrl: 'tickers-module-template.html',
          controller: function($scope, $state) {
            console.log('Tickers init', $state.params);
        
            $scope.tickers = [
              { id: 1, ticker: 'AAPL' },
              { id: 2, ticker: 'GOOG' },
              { id: 3, ticker: 'TWTR' }
            ];
            
            $scope.clickTicker = function(ticker) {
              console.log(' ')
              console.log('Ticker clicked!')
              $state.go('dashboard', { ticker: ticker });
            }
          }
        },
        'tags@dashboard' : {
          templateUrl: 'tags-module-template.html',
          controller: function($scope, $state) {
            const tags_model = [
              {
                ticker: 'AAPL',
                tags : [{ id: 1, term: 'iPhone 7' }, { id: 2, term: 'iPhone 8' }, { id: 3, term: 'Tim Cook' }]
              },
              {
                ticker: 'GOOG',
                tags : [{ id: 4, term: 'Pixel' }, { id: 5, term: 'Pixel XL' }, { id: 6, term: 'Chrome Book' }]
              },
              {
                ticker: 'TWTR',
                tags : [{ id: 7, term: 'tweet' }, { id: 8, term: 'retweet' }, { id: 9, term: 'moments' }]
              }
            ];
            
            function matchTags(ticker, model) {
              return model.filter(function(obj){
                if (obj.ticker === ticker) { return obj; }
              });
            }
            
            $scope.tags_model = matchTags($state.params.ticker.ticker, tags_model)[0];
            
            $scope.clickTag = function(tag) {
              $state.go('tags', { tag: tag });
            }
            
            console.log('Tags init', $state.params);
            // console.log(' Tags model', tags_model);
          }
        },
        'social@dashboard' : {
          templateUrl: 'social-module-template.html', 
          controller: function($state) {
            console.log('Social init', $state.params);
          }
        }
      }
    }

    $stateProvider
      .state(login)
      .state(dashboard);
});

Thoughts, would an architecture like this work? Basically login would navigate to a container state which will contain 2 components (dashboard and feed) each with their own internal states?

解决方案

I could resolve this issue depending on which state you're coming from. Based on the fact that you only want the feed to be loaded 'once' when dashboard is loaded, I'm checking the name of the previous state, and if it is not dashboard, only then I'll proceed with executing the rest of the controller code. Here is the plunker. Note that this is not very scalable approach if more states are added and if someone else has a better approach, I'd really like to see that.

I changed the controller code as follows:

feed.component('feedModule', {
  templateUrl: 'feed-module-template.html',
  controller: function($scope, $state) {
    var previousState = $state.params.previousState.name;
    if(previousState !== 'dashboard') {
      console.log('Feed init (only once)', $state.params); //do whatever u want here
    }
  }
});

I'm passing around previous state as params to other states like this:

controller: function($state) {
  this.login = function() {
    $state.go('dashboard', {previousState : { name : $state.current.name }})
  }
}

Look at the full plunker here to see if this helps your case!

这篇关于如何防止另一个$ state更新时刷新特定的$ state的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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