簡體   English   中英

$ scope傳遞有延遲

[英]$scope passing has a Delay

我正在構建一個用於多種用途的Angular彈出系統。 它的工作方式是我有一個名為bitPopup的指令,該指令將三個變量傳遞給( typeactiondata ),如下所示:

的index.html

<bit-popup type="popup.type" action="popup.action" data="popup.data"></bit-popup>

popup.js

app.directive('bitPopup', function () {
  return {
    restrict: 'E',
    template: html,
    scope: {
      type: '=',
      action: '=',
      data: '='
    },
    [***]
  }
}

然后,彈出控制器根據類型加載另一個指令:

popup.html (上面顯示的HTML模板)

<div class="pop-up" ng-class="{visible: visible}" ng-switch="type">
  <bit-false-positive-popup ng-switch-when="falsePositive" type="type" action="action" data="data"></bit-false-positive-popup>
</div>

false_positives.js (包含bitFalsePositivePopup指令)

[...]
scope: {
  type: '=',
  action: '=',
  data: '='
}
[...]

然后,用於bitFalsePositivePopup指令的html模板顯示data一些屬性。

現在,我觸發彈出窗口的方式如下:

  1. 從包含bitPopup指令的指令內部的模板中,我將更改$scope.popuptypeactiondata
  2. 我將做$scope.$broadcast('showPopup');
  3. 由於$scope.$on('showPopup', [...]}); bitPopup指令將作出反應$scope.$on('showPopup', [...]}); 並使彈出窗口可見。

現在,這確實很奇怪,發生在第一次嘗試的地方(彈出窗口打開並顯示了正確的data信息),但是在第一次嘗試之后,它將顯示先前嘗試的data

現在更奇怪的是,我第一次嘗試記錄信息時發現:

  • 在調用$scope.$broadcast('showPopup');之前,在index.html上的 $scope.popup $scope.$broadcast('showPopup'); 顯示正確的信息。
  • bitPopup指令處的$scope.data顯示null
  • bitFalsePositivePopup指令處的$scope.data顯示正確的信息。

在第二次嘗試:

  • index.html上的$scope.popup再次正確。
  • bitPopup指令處的$scope.data顯示上一次嘗試的信息
  • bitFalsePositivePopup指令也是bitFalsePositivePopup

另一個奇怪的事情是,當我使用$scope.$apply()可以正常工作時,僅顯示$apply already in progress錯誤。 我知道在這種情況下不應該使用$scope.$apply() ,因為這都是Angular事件。 但是,傳遞的范圍怎么可能總是落后一步呢?

首先我做錯了什么嗎?

編輯:

由於amahfouz的回答,我決定發布更多代碼進行澄清。 我省略了一些不重要的細節,以使閱讀更加清晰。

的index.html

<div class="falsePositives" ng-controller="falsePositives">
  <i class="fa fa-minus color-red" ng-click="triggerPopup('falsePositive', 'delete', {detection: getDetection(row.detection, row.source), source: row.source, triggers: row.triggers, hash: row.hash, date: row.date})"></i>
  <i class="fa fa-pencil" ng-click="triggerPopup('falsePositive', 'edit', {detection: getDetection(row.detection, row.source), source: row.source, triggers: row.triggers, hash: row.hash, date: row.date})"></i>

  <bit-popup type="popup.type" action="popup.action" data="popup.data"></bit-popup>
</div>

index.js

var app = require('ui/modules').get('apps/falsePositives');

app.controller('falsePositives', function ($scope, $http, keyTools, bitbrainTools, stringTools) {
  function init() {
    $scope.getDetection = getDetection;

    $scope.popup = {
      type: null,
      action: null,
      data: null
    };
  }

  function getDetection(hash, source) {
    return {
      'ids': 'BitSensor/HTTP/CSRF',
      'name': 'CSRF Detection',
      'description': 'Cross domain POST, usually CSRF attack',
      'type': [
        'csrf'
      ],
      'severity': 1,
      'certainty': 1,
      'successful': false,
      'input': ['s'],
      'errors': []
    };
  }

  $scope.triggerPopup = function (type, action, data) {
    $scope.popup = {
      type: angular.copy(type),
      action: angular.copy(action),
      data: angular.copy(data)
    };

    test();

    $scope.$broadcast('showPopup');
  };

  function test() {
    console.log('$scope.popup: ', $scope.popup);
  }
}

popup.html

<div class="pop-up-back" ng-click="hidePopup()" ng-class="{visible: visible}"></div>
<div class="pop-up" ng-class="{visible: visible}" ng-switch="type">
  <bit-false-positive-popup ng-switch-when="falsePositive" type="type" action="action" data="data"></bit-false-positive-popup>
</div>

popup.js

var app = require('ui/modules').get('apps/bitsensor/popup');

app.directive('bitPopup', function () {
  return {
    restrict: 'E',
    template: html,
    scope: {
      type: '=',
      action: '=',
      data: '='
    },
    controller: function ($scope) {
      $scope.visible = false;

      $scope.$on('showPopup', function () {
        console.log('$scope.data: ', $scope.data);
        $scope.visible = true;
      });

      $scope.$on('hidePopup', function () {
        hidePopup();
      });

      function hidePopup() {
        $scope.visible = false;
      }

      $scope.hidePopup = hidePopup;
    }
  };
});

false_positives.js

var app = require('ui/modules').get('apps/bitsensor/falsePositives');

app.directive('bitFalsePositivePopup', function () {
  return {
    restrict: 'E',
    template: html,
    scope: {
      type: '=',
      action: '=',
      data: '='
    },
    controller: function ($scope, objectTools, bitbrainTools, keyTools) {

      function init() {
        console.log('$scope.data @ fp: ', $scope.data);
      }

      function hidePopup() {
        $scope.data = null;
        $scope.$emit('hidePopup');
      }

      $scope.$on('showPopup', function () {
        init();
      });

      init();

      $scope.hidePopup = hidePopup;
    }
  }
}

如果沒有其余代碼,我只能猜測:您要么需要在顯示彈出窗口時使用Promise,要么使用$ apply服務對彈出窗口的可見性進行更改。

在$ timeout中包圍您的$ broadcast事件,如下所示:

$timeout(function() {
  $broadcast('eventName');
});

它將等待$ scope更新,然后觸發事件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM