【问题标题】:How to pass $state variable into 2 other sibling $states?如何将 $state 变量传递给其他 2 个同级 $states?
【发布时间】:2017-03-17 19:02:41
【问题描述】:

Plnkr:https://plnkr.co/edit/Brmcxd2LjGVJ6DXwuJtF?p=preview

架构:

$login -> $container(包含$dashboard$feed),dashboard包含:$tickers$tags$viewHeader$socialMedia组件。

目标:

tags 需要通信并将标签对象发送到viewHeadersocialMedia 状态。

预期:

Login 之后,在标签列表中选择一个按钮应该会将 tag 发送到 ViewHeaderSocialMedia 状态/组件。

结果:

Login 之后,在标签中选择一个按钮并转到 $state dashboard $states 以进行 ViewHeaderSocialMedia 刷新但视图模型变量{{ term }} 不会更新为任一组件中的相应标记。

设计说明:

我试图通过混合状态、组件、兄弟组件和视图来解决的问题是,当任何状态发生变化时,应用程序中的每个组件都会刷新/重新启动。 $state.go('dashboard'...

这并不理想,我想要的是确保只有需要刷新的组件,刷新。

IE:当我选择 TickerTag 时,我不希望 Feed 组件每次都刷新。但是,用户应该能够在 Feed 组件中执行操作,并且它将更新所有其他组件。

这就是我创建container 状态来同时保存dashboardfeed 状态的原因。最初我的所有东西都处于dashboard 状态,并且任何时候$state.go('dashboard' 发生feed 组件也会刷新。如果有更好的方法来解决这个问题lmk! :)

PS:开始学习使用 ui-router 进行状态管理,以消除对 $rootScope 的依赖。到目前为止,我的真实应用程序要稳定得多,但有一个烦人的功能,即每个组件都会刷新/重新启动。


在下面的屏幕截图中,我可以清楚地看到正确的 tag 被传递到正确的 $states,但 {{ term }} 没有更新。

代码 sn-ps(Plnkr 中的完整代码)

app.container.html(容器状态)

<div>
    <dashboard-module></dashboard-module>
    <feed-module></feed-module>
    <!--<div ui-view="dashboard"></div>-->
    <!--<div ui-view="feed"></div>-->
</div>

dashboard.html(仪表板状态)

<div class="jumbotron text-center">
    <h1>The Dashboard</h1>
</div>

<div class="row">
  <tickers-module></tickers-module>

  <!-- Tags component goes here -->
  <div ui-view></div>

  <view-module></view-module>

  <social-module></social-module>
</div>

^ 我使用上面的&lt;div ui-view&gt; 来加载标签状态的原因是,到目前为止,这是我可以初始化标签模块并显示来自代码组件的标签列表的唯一方法。

tickers 组件控制器:

tickers.component('tickersModule', {
  templateUrl: 'tickers-module-template.html',
  controller: function($scope, $state) {
    console.log('Tickers component', $state.params);
    $scope.tickers = [
      { id: 1, ticker: 'AAPL' },
      { id: 2, ticker: 'GOOG' },
      { id: 3, ticker: 'TWTR' }
    ];

    $state.go('tags', { ticker: $scope.tickers[0] }); // <---

    $scope.clickTicker = function(ticker) {
      $state.go('tags', { ticker: ticker });
    }
 }

^ 上面的

var tags = angular.module('tags', ['ui.router'])
tags.config(function($stateProvider) {

  const tags = {
    parent: 'container',
    name: 'tags',
    url: '/tags',
    params: {
      ticker: {}
    },
    template: '<tags-module></tags-module>',
    controller: function($scope, $state) {
      console.log('Tags state', $state.params);
    }
  }

  $stateProvider.state(tags);
})
tags.component('tagsModule', {
  templateUrl: 'tags-module-template.html',
  controller: function($scope, $state) {
    console.log('Tags component', $state.params);
    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; }
      });
    }

    $state.params.ticker = $state.params.ticker || {};
    $scope.tags_model = matchTags($state.params.ticker.ticker, tags_model)[0];

    $scope.clickTag = function(tag) {
      console.log(' Tag clicked', $state);
      $state.go('dashboard', { tag: tag });
    }
  }
});

标签列表中的点击功能:

$scope.clickTag = function(tag) {
  console.log(' Tag clicked', $state);
  $state.go('dashboard', { tag: tag });
}

社交媒体控制器:

social.component('socialModule', {
  templateUrl: 'social-module-template.html',
  controller: function($scope, $state) {
    console.log('Social component', $state.params);
    $scope.term = $state.params.tag.term;
  }
});

viewHeader 控制器:

view.component('viewModule', {
  templateUrl: 'view-module-template.html',
  controller: function($scope, $state) {
    console.log('View component', $state.params);
    $scope.term = $state.params.tag.term;
  }
});

奇怪的组件加倍

刚刚注意到这一点,在单击一个标签并闯入 social.component 之后。看起来仪表板组件正在重新渲染一瞬间代替标签组件:


更新,通过在标签中添加{ refresh: true } 到 $state.go 解决了这里的问题。但是请注意,这仍然没有解决我最初的任务,即阻止 feed.component 刷新。所以最终会使用服务。

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

【问题讨论】:

  • stackoverflow.com/questions/24575491/… ,请检查此链接,它应该可以解决您的问题。基本上你需要解决你的参数。
  • @Pramod_Para 我不确定是不是这样,因为我有我的参数命名。此外,在我的 plnkr 中,即使我在标签按钮单击时进入状态 dashboard,状态也不会初始化,组件也不会再次出现。
  • 可以吗,如果我为您提供一个不同的示例,它将指导您如何将参数从父状态传递到兄弟状态。?
  • 那太棒了,我也想做的是确保只有我想要更新的兄弟状态刷新,而不是我不想更新的状态。 IE:在我的示例中为feed。股票代码 -> 更新标签 -> 更新社交,提要保持不变并且不会重新初始化。
  • 抱歉,对我来说这是漫长的一天,今天凌晨 3 点肯定会更新您的 plunkr。

标签: javascript angularjs routing angular-ui-router state-management


【解决方案1】:

我已经更新了你的插件

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

解决方案相当简单。不要使用$state,而是在依赖注入中使用$stateParams,这是一个单例,所以如果你像我在更新的plunker中那样引用它:

$scope.params = $stateParams

然后是显示值

{{params.ticker.ticker}}

将 2 路绑定到 $stateParams 并在每次更改状态时相应更新

---编辑---

我通过服务添加了另一个解决方案 https://plnkr.co/edit/oQNAHv7tAS8LR9njOUAX?p=preview

.service('awesomeTag', function($rootScope){
  var self = this;
  $rootScope.$on('$stateChangeSuccess', function(_event, _toState, toParams){
    self.tag = toParams.ticker.ticker
  })

})

【讨论】:

  • 嘿 Maury,我看到你正在传递代码,但是你如何传递来自 tags.component 的标签呢?另一件事,我在您的 plnkr 中看不到社交或视图组件的控制器日志。
  • $state.go('dashboard', { tag: tag }); 这是需要更新socialview 中的标签$stateParams 的操作。目前,tag 对象没有到达那里。有没有?
  • 好的,给我几分钟,刚吃完午饭回来;)
  • 没有问题! :D 我自己还在努力解决这个问题。在这里创建了 2 个新的 plnkrs plnkr.co/edit/P0DIEDxLU4Wlm9L0bcTi?p=preview 和一个更干净的:plnkr.co/edit/2h6fV5yTjeUqLP3SvbvO?p=preview 另请参阅dashboard.html。我认为问题在于,当我进入状态dashboard 时,它会在一段时间内再次用整个仪表板替换 ui-view 中的标签组件。你必须在 social.component 控制器中设置一个断点才能看到。
  • 是的,路由器的配置让它闪烁,根本问题在于你在控制器初始化中有 $state.go 的ticker组件
【解决方案2】:

我更新了你的 plunker here。您的代码中的问题在这里:

view.component('viewModule', {
  templateUrl: 'view-module-template.html',
  controller: function($scope, $state) {
    console.log('View component', $state.params);
    $scope.term = $state.params.tag.term; //culprit line
  }
});

您需要做的是使用$stateParams 来检索参数。我将 viewModule 中的代码更改如下:

controller: function($scope, $stateParams) {
    console.log('View component', $stateParams);
    $scope.tickerObj = $stateParams;     
}

然后相应地更新view-module-template.html 以使用tickerObj,如下所示:

{{ tickerObj.ticker.ticker }}

社交模块也是如此。

了解其工作原理的简单示例如下:

$stateProvider.state('stateName', {
    url: '/stateName',
    controller: 'myCtrl',
    params: { //this can also be used to give default values for route params
        obj: null
    }
});

function myCtrl($stateParams) {
    console.log($stateParams);   //will display the obj parameter passed while transitioning to this state
}

$state.go('stateName', {obj:yourObj}); //passing obj as param to stateName state, this can be retrieved using $stateParams. 

这与您的last 问题中发生的问题类似。

我注意到您的代码存在另一个问题。单击任何标签(例如转推、时刻、推文)时,它会再次将代码更改为“AAPL”。这是预期的行为吗? (如果没有,这是因为当您在单击代码后转换到仪表板状态时,所有模块都被重新初始化。导致这种情况的行是

$state.go('tags', { ticker: $scope.tickers[0] });

希望这会有所帮助!

更新:

我更新了 plunker here。我注释掉了这一行:

$state.go('tags', { ticker: $scope.tickers[0] }); 

默认情况下,每次我们进入仪表板状态时都将ticker设置为apple。我现在还将股票代码和标签对象传递给视图和社会状态。如果您查看控制台,您将能够获得正确的值来标记和标记这两种状态。让我知道这是否适合您。

您可以通过查看控制台日志来验证标签和股票代码值是否正在传递到视图和社交组件中。 这是一个sn-p:

【讨论】:

  • 嘿,我仍然无法将标签从标签组件中获取到视图或社交中,你是怎么做到的? plnkr.co/edit/P0DIEDxLU4Wlm9L0bcTi?p=preview我不想让股票通过。而且我没有在 $stateParams 中看到该标签,即使在确保它是所有州的参数之后也是如此。
  • 好的,我看到标签对象正在传递到 socialMedia 组件中。 $scope.tagObj 被设置。但后来它丢失了......当我点击标签按钮时再次丢失。并暂停调试器,我可以看到仪表板被加载了两次。我认为这是我的问题,有什么办法吗?
  • 我在看。
  • 好的,点击功能现在可以工作了,但是在开始时看到标签组件丢失了。同样单击一个标签,现在我们可以看到dashboard.html 正在dashboard.html 中重新加载。对不起,我认为这个应用程序现在太复杂了。看看这个 plnkr,它的简化,我没有使用 ui-view 来加载标签,没有不必要的状态配置。如果我们能做到这一点,这也将结束这个问题:plnkr.co/edit/2h6fV5yTjeUqLP3SvbvO?p=preview
  • 这有一个我之前解决的“无法读取未定义的属性术语”问题。请修复该问题并更新 plunker,然后我才能尝试解决此问题。
【解决方案3】:

发布此内容是因为这是解决此问题并正确构建应用程序的正确方法:

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

这里我正确地使用了子状态和命名视图。

container-template.html

<div>
  <div class="fl w100">
      <em>Container component module scope</em>  
  </div>

  <div ui-view="dashboard"></div>

  <div ui-view="feed" class="fl"></div>
</div>

标签状态

const tags = {
  name: 'container.dashboard.tickers.tags',
  url: '/tags',
  params: {
    ticker: {},
    tag: {}
  },
  views: {
    'tags' : {
      templateUrl: 'tags-list.html',
      controller: function($scope, $state) {
        console.log('tags-list controller', $state)
        $scope.ticker = $state.params.ticker;

状态导航到 child.child 状态:

$scope.clickTicker = function(ticker) {
    $state.go('container.dashboard.tickers.tags', { ticker: ticker });
}

【讨论】:

    猜你喜欢
    • 2021-02-26
    • 2013-06-03
    • 2021-05-22
    • 1970-01-01
    • 2021-08-10
    • 2023-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多