ng-switch何时完成渲染?

时间:2014-10-27 00:43:22

标签: javascript html angularjs angular-ui-router ng-switch

我正在使用ui-router并尝试实例化一个小部件,该小部件将id作为参数作为DOM指定的元素。这个DOM元素在<div ng-switch>中,我希望在保证元素存在时调用widget构造函数。

<div ng-switch on="state">
  <div ng-switch-when="map">
    <div id="map"></div>
  </div>
</div>

ui-router lifecycle开始,我知道我应该加入$viewContentLoaded。但是,这并不起作用 - ng-switch中的DOM元素不会在此时创建:

app.config(['$stateProvider', function ($stateProvider) {
  $stateProvider
    .state('/', {url: '/', templateUrl: 'index.html'})
    .state('map', {url: 'map', templateUrl: 'map.html', controller: 'MapCtrl'})
}]);

app.controller('MapCtrl', ['$rootScope', '$scope', '$state', function MapCtrl($rootScope, $scope, $state) {
  $scope.state = $state.current.name;  // expose the state to the template so we can ng-switch. Apparently there's no better way: https://github.com/angular-ui/ui-router/issues/1482

  $scope.$on('$viewContentLoaded', function mapContentLoaded(event, viewConfig) {
    var mapElement = document.getElementById('map');
    console.log('Attempting to create map into', mapElement);
    var map = new google.maps.Map(mapElement);  // <-- but mapElement will be null!
  });
}]);

在控制器中使用50毫秒setTimeout()的工作是什么,这很脆弱,但到那时创建了DOM元素。或者,我可以设置一个间隔,检查是否存在map DOM元素,并清除它找到的间隔。

找出ng-switch何时呈现DOM的正确的方法是什么?这isn't documented

这里是Plunkr

1 个答案:

答案 0 :(得分:1)

我认为你正陷入许多经验丰富的前端开发人员使用Angular时陷入困境的陷阱。在大多数其他JS库中,我们在创建DOM之后对其进行修改,然后向其添加功能。但是,在Angular中,功能在HTML中定义。通过使用指令创建功能和交互性。

在jQuery中这样的事情很好:

<div id="foobar">
    Click here to do stuff
</div>

<script type="text/javascript">
    $(function () {
        $('#foobar').on('click', function () {
            someService.doStuff();
        });
    });
</script>

而Angular中的 类似下面的内容更具惯用性:

<div id="foobar" ng-controller="Main" ng-click="doStuff()">
    Click here to do stuff
</div>

<script type="text/javascript">
    app.controller('Main', ['$scope', 'somerService', function ($scope, someService) {
        $scope.doStuff = function () {
            someService.doStuff();
        }
    }]);
</script>

至于你的GoogleMap指令,这是迄今为止完成它的最简单方法。虽然这是非常基本的,可能不会做你需要的一切。

app.directive('googleMap', [function() {
    return {
      link: function(element) {
        new google.maps.Map(element);
      }
    }
  }
]);

您的map.html

<div ng-switch on="state">
  <div ng-switch-when="map">
    <div google-map id="map"></div>
  </div>
</div>

正如您所提到的,这会在每次触发控制器时重新创建Google地图。另一种方法是保存元素和Map api并在后续调用中替换它:

app.directive('googleMap', [function () {
    var googleMapElement,
            googleMapAPI;
    return {
        link: function (element) {
            if (!googleMapElement || !googleMapAPI) {
                googleMapAPI = new google.maps.Map(element);
                googleMapElement = element;
            }
            else {
                element.replaceWith(googleMapElement);
            }

        }
    }
}]);