1

所以我有一个控制器和指令。我无法理解为什么我的控制器在我的指令之后运行。我已经搜索堆栈试图找到答案,但似乎大多数答案都是个案。

我的控制器最简单的形式就是这样

app.controller('MyCtrl', ['$scope', function ($scope){
$scope.initAddress = {
    place_id: "",
    geometry: {
        location: {
            A: "",
            F: ""
        }
    },
}
$scope.gotoLocation = function (placeId) {
                   $scope.initAddress = {
                       place_id: "placeId",
                       geometry: {
                           location: {
                               A: placeId.geometry.location.lat(),
                               F: placeId.geometry.location.lng()
                           }
                       }
}};}]);

当我单击我的 ng-click 按钮时,我将转到 gotoLocation 范围函数并重新定义 $scope.initAddress。我的HTML如下:

<div class="row">
<my-map address="initAddress"></my-map>
</div>
<div ng-repeat="place in placelistData.placeList">
    <button ng-click="gotoLocation(place.id)">{{place.id}}</button>
</div>

现在当我查看我的指令时,我正在使用

 .directive('myMap', function () {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            address: '=?',
        },
        template: '<div class="dp-places-map-wrapper"><input type="text" class="dp-places-map-input"><div class="dp-places-map-canvas"></div></div>',

        link: function (scope, element, attrs) {
scope.$watch('address', function () {
   if (map && scope.address)
   map.setCenter(getLocation(scope.address));
 });
 }

现在,当我单击按钮时,它会运行到控制器和 $scopes.initAddress 并且不会点击 $scope.watch。当我再次点击它时,它首先点击 $scope.watch 然后它转到我的控制器并相应地更新。我怎样才能改变它,以便它先击中控制器,然后 $scope.watch 捕捉控制器中的变化。而不是先运行 $scope.watch 然后运行控制器。

谢谢您的帮助

4

2 回答 2

3

关于理解为什么控制器在我的指令之后运行。

根据角度 $compile 阶段,总是在使用深度优先遍历算法的控制器之前调用指令。

原因是,指令是一个可重用的组件。所以它必须在控制器被调用之前被实例化。

例如,您的 html 可能看起来像这样

<body ng-app="demo">
<div ng-controller="controller1">
     <my-map address="initAddress"></my-map>
</div>
<div ng-controller="controller2">
    <my-map address="initAddress"></my-map>   
</div>
<div ng-controller="controller3">
<my-map address="initAddress"></my-map>
 </div></body>

这里 initAddress 将是各个控制器“controller1”、“controller2”和“controller3”中的范围变量。因此,总是会在使用深度优先遍历算法的控制器之前调用指令。

这是指令的生命周期

  1. 指令被实例化
  2. 调用外部控制器,其中声明了指令。
  3. 指令内定义的控制器被调用。
  4. 如果定义了预链接,则会被调用。
  5. 如果定义了 postlink,则称为 注意:如果定义了链接函数,则始终是 postlink 函数。如果声明了编译函数,则永远不会调用链接函数。

请查看帖子了解更多详情。 http://yogeshtutorials.blogspot.in/2015/12/angularjs-directive-lifecycle.html

于 2015-12-07T05:54:08.117 回答
1

当 AngularJS 编译 DOM 时,它会以深度优先、自上而下的方式遍历 DOM 树。当它遍历 DOM 时,它会实例化指令控制器。然后,当它到达本地 DOM 树分支的底部时,它开始以自下而上的方式链接指令,同时它会返回分支。这并不意味着所有指令控制器都在所有指令链接之前运行;它只是意味着在本地 DOM 分支中,指令控制器在链接之前被实例化。

所以在你的情况下,$scope.initAddress = {...}首先被击中。您是否尝试过在链接函数中初始化地址?

于 2015-12-07T04:47:43.400 回答