【问题标题】:AngularJS better way to manage partials and controller dataAngularJS 更好的方法来管理部分和控制器数据
【发布时间】:2012-11-16 23:12:14
【问题描述】:

我一直在 AngularJS 中使用指令,它使用从控制器的 $scope 获取的数据构建一个 HTML 元素。当我的控制器从服务器获取它的 JSON 数据时,我让我的控制器设置了一个 $scope.ready=true 变量。这样,指令就不必在每次获取数据时一遍又一遍地构建页面。

以下是事件发生的顺序:

  1. 控制器页面加载路由并触发控制器功能。

  2. 页面扫描指令并触发此特定指令。

  3. 指令构建元素并评估其表达式并继续执行,但是当指令链接函数被触发时,它会等待控制器“准备好”。

  4. 准备就绪后,会触发一个内部函数,然后继续构建局部函数。

这行得通,但代码很乱。我的问题是有没有更简单的方法来做到这一点?我可以抽象我的代码以便在我的控制器触发事件​​后触发它吗?而不必制作这个 onReady 内部方法。

这是它的样子(它可以工作,但很难测试):

angular.module('App', []).directive('someDirective',function() {

  return {

    link : function($scope, element, attrs) {

      var onReady = function() {
        //now lets do the normal stuff
      };

      var readyKey = 'ready';
      if($scope[readyKey] != true) {
        $scope.$watch(readyKey, function() {
          if($scope[readyKey] == true) {
            onReady();
          }
        });
      }
      else {
        onReady();
      }

    }

  };

});

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    您可以在控制器中使用$scope.$emit,在指令中使用$rootScope.on("bradcastEventName",...);。好处是指令是解耦的,您可以随时将其从项目中取出。您可以对应用程序的所有指令和其他“正在运行”的组件重复使用相同的模式来响应此事件。

    【讨论】:

    • 我得到了 $rootScope,但是当我从控制器 $scope 中触发 $emit 时,它没有接收到它?有什么想法吗?
    • 事实证明它可以工作,但是控制器代码运行得更快,并且在指令有机会设置 $on 事件之前执行并发出响应。关于如何解决这个问题的任何想法?
    • 我明白了,好吧,也许如果你尝试使用 defer 和 promise ($q)。现在不是从控制器公开值,而是​​公开“承诺”,您可以稍后在 $scope.promise.then(.....); 之类的指令中使用它,无论如何,如果我没记错的话,您的指令将用于由您提到的控制器控制的视图。请记住,在这种情况下,angularjs 首先 instate 控制器,然后编译(如果之前未编译)您的视图。编译完成后,它会在你的指令中调用 then link 方法。
    • 顺便说一句,如果您的事件顺序需要按照您在问题中描述的顺序,您不必担心控制器是否准备就绪,只需 $scope.$watch("name", function(){}) 并且您的指令将捕获下一个更改,并在链接时尝试读取 $scope.something 即使它未定义。
    • 有没有办法在 jsfiddle 中提供给我?
    【解决方案2】:

    我发现了两个问题:

    • 在后台触发任何 XHR 请求都不会阻止模板加载。
    • 将数据应用于$scope 变量与实际将该数据应用于页面绑定之间存在差异(当$scope 被消化时)。因此,如果您将数据设置为范围,然后触发事件以通知部分范围已准备好,那么这将无法确保该部分的数据绑定已准备好。

    所以要解决这个问题,最好的解决方案是:

    1. 使用此插件来管理控制器和以下任何指令之间的事件处理: https://github.com/yearofmoo/AngularJS-Scope.onReady

    2. 不要将您希望 JavaScript 函数拾取和使用的任何数据放入指令模板 HTML。因此,例如,如果您有一个如下所示的链接:

      <a data-user-id="{{ user_id }}" href="/path/to/:user_id/page">My Page</a>

      那么问题是指令必须从data-user-id 属性中准备:user_id 值,获取href 值并替换数据。这意味着该指令必须不断检查 data-user-id 属性以查看它是否存在(每隔几分钟检查一次 attrs 哈希)。

      相反,直接在 URL 中放置一个不同的范围变量

      <a href="/path/to/{{ directive_user_id }}/page">My Page</a>

      然后把它放在你的指令中:

      $scope.whenReady(function() { $scope.directive_user_id = $scope.user_id; });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-19
      • 1970-01-01
      • 2013-03-31
      • 1970-01-01
      • 2013-05-19
      • 1970-01-01
      • 2014-09-14
      • 1970-01-01
      相关资源
      最近更新 更多