范围函数执行但 HTML 永远不会改变

Scope function executes but the HTML never changes

AngularJS 范围变量的范围

我的 HTML

里有这个
{{searchDialog.visible}}

这在我的控制器中

$scope.searchDialog = {'visible' : false};   // initialize

$scope.MarkerClicked = function(e)
{
    $scope.searchDialog.visible = true;
}

这些是 $scope.searchDialog 的唯一提及。我指向 $scope.MarkerClicked 函数并观察值切换为 true,但 HTML 永远不会改变。

我做错了什么?是否存在范围问题(无双关语)?

啊哈!! $scope.MarkerClicked 是点击 Leaflet 地图标记的回调

var marker = L.marker(pubLatLng,
    {
        draggable: false,
        title: title,
        icon: new L.DivIcon({
            html: '<img class="my-div-image" src="js/3rd_party/leaflet/images/'
                       + iconImage + '" />'
                + '<span style="color:red">' + companyName + '</span>',
        })
    }).addTo($scope.map).on('click', $scope.MarkerClicked);

这是否以某种方式导致了我的问题?我看不出如何,因为标记是在 $scope 函数中添加的,回调也在 $scope 函数中处理。

此问题与Angular Digest Cycle有关,因为调用了MarkerClicked方法,但它不在Angular Digest Cycle的范围内,所以您必须明确调用摘要循环。

要解决这个问题,请看下面的代码片段,如果我们不添加 $scope.$apply(),$scope.message 将不会更新,添加 $scope 后下面示例中的 .$apply() 会自动触发 $rootScope.$digest()。结果,观察者像往常一样被解雇并且视图更新。

/* What happens with $apply */ 
angular.module('myApp',[]).controller('MessageController', function($scope) {
    
      $scope.getMessage = function() {
        setTimeout(function() {
          $scope.$apply(function() {
            //wrapped this within $apply
            $scope.message = 'Fetched after 3 seconds'; 
            console.log('message:' + $scope.message);
          });
        }, 2000);
      }
      
      $scope.getMessage();
    
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.16/angular.min.js"></script>

<body ng-app="myApp">
  <div ng-controller="MessageController">
    Delayed Message: {{message}}
  </div>  
</body>

第三方应用程序创建的事件需要使用$scope.$apply引入AngularJS框架:

var marker = L.marker(pubLatLng,{
    draggable: false,
    title: title,
    icon: new L.DivIcon({
        html: '<img class="my-div-image" src="js/3rd_party/leaflet/images/'
                   + iconImage + '" />'
            + '<span style="color:red">' + companyName + '</span>',
    })
}).addTo($scope.map).on('click', function(e) {
    $scope.$apply(function() {
        $scope.MarkerClicked(e)
    });
});

AngularJS modifies the normal JavaScript flow by providing its own event processing loop. This splits the JavaScript into classical and AngularJS execution context. Only operations which are applied in the AngularJS execution context will benefit from AngularJS data-binding, exception handling, property watching, etc... You can also use $apply() to enter the AngularJS execution context from JavaScript.

AngularJS Developer Guide - Integration with the browser event loop