4

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

建筑学:

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

目标:

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

预期的:

之后Login,在标签列表中选择一个按钮应将其发送tagViewHeaderSocialMedia状态/组件。

结果:

之后Login,在标签中选择一个按钮并转到 $statedashboard以用于ViewHeaderSocialMedia刷新,但视图模型变量{{ term }}不会使用任一组件中的适当标签进行更新。

在此处输入图像描述

设计说明:

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

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

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

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

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

在此处输入图像描述


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

在此处输入图像描述

在此处输入图像描述

代码片段(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>

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

股票代码组件控制器:

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 });
    }
 }

^ 上面的 <--- 允许标签状态加载标签组件元素并根据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

在此处输入图像描述

4

3 回答 3

2

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

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. 

这类似于您上一个问题中发生的问题。

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

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

希望这可以帮助!

更新:

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

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

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

您可以通过查看控制台日志来验证标签和代码值是否正在传递到视图和社交组件中。这是一个片段: 在此处输入图像描述

于 2017-03-21T02:06:00.483 回答
2

我已经更新了你的 plunker

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

解决方案相当简单。而不是在依赖注入中使用$stateuse$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
  })

})
于 2017-03-20T22:06:06.953 回答
0

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

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

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

在此处输入图像描述

容器模板.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 });
}
于 2017-03-24T14:02:50.560 回答