Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 什么';从控制器中触发jQuery DOM操作的正确方法是什么?_Javascript_Angularjs_Angularjs Controller - Fatal编程技术网

Javascript 什么';从控制器中触发jQuery DOM操作的正确方法是什么?

Javascript 什么';从控制器中触发jQuery DOM操作的正确方法是什么?,javascript,angularjs,angularjs-controller,Javascript,Angularjs,Angularjs Controller,所以我一直在读控制器中的jQuery操作是不好的做法,但我不清楚为什么,或者如何纠正 下面是Youtube教程中的代码,即使是视频创建者的评论也是一个坏主意,但没有解释为什么会这样做,而且还会继续使用这种坏行为 发件人: 解决方案: 根据Langdon在下面的回答,我为自己的工作得出了以下工作代码,它稍微源自上面的示例代码: var ProjectListCtrl = function ($scope, Project) { $scope.projects = Project.query

所以我一直在读控制器中的jQuery操作是不好的做法,但我不清楚为什么,或者如何纠正

下面是Youtube教程中的代码,即使是视频创建者的评论也是一个坏主意,但没有解释为什么会这样做,而且还会继续使用这种坏行为

发件人:

解决方案:

根据Langdon在下面的回答,我为自己的工作得出了以下工作代码,它稍微源自上面的示例代码:

var ProjectListCtrl = function ($scope, Project) {
    $scope.projects = Project.query();
    $scope.delete = function() {
        var thisElem = this;
        var thisProject = thisElem.project;
        var id = thisProject.id;
        Project.delete({id: id}, function() {
            var idx = $scope.projects.indexOf(thisProject);
            if (idx !== -1) {
                thisElem.destroy('removeItem('+idx+')');
            }
        });
    }

    $scope.removeItem = function(idx) {
        $scope.projects.splice(idx, 1);
    }

}

app.directive('fadeOnDestroy', function() {
    return function(scope, elem) {
        scope.destroy = function(funcComplete) {
            elem.fadeOut({
                complete: function() {
                    scope.$apply(funcComplete)
                }
            });
        }
    }
});
这与兰登的回答有几点不同。我不想在
ngClick
回调中添加参数,所以我将它存储在
thisProject
中。此外,示例和我的代码需要在
$http
成功回调中调用
destroy
,因此我将单击的元素存储在
thisElem
中,而不是不再相关的
this

更新2


进一步更新了我的解决方案,以反映funcComplete实际上没有修改原始的$scope。

处理此问题的角度方法是通过指令。我找到了一个完美的例子来回答你下面的问题,虽然它没有我想要的那么干净。其思想是创建一个用作HTML属性的指令。当元素绑定到控制器的作用域时,将触发
链接
函数。该函数淡入元素(完全可选),并公开销毁方法供控制器稍后调用

更新:根据注释进行修改,以实际影响范围。对这个解决方案不感兴趣,甚至更为简捷,因为最初的作者在他的destroy回调中调用了
complete.apply(scope)
,但在回调函数中没有使用
this

更新2:由于指令是使回调异步的指令,因此最好使用
scope.$apply
,但请记住,如果在指令中使用隔离作用域,这可能会变得奇怪

HTML:


至于原因,我认为这仅仅是为了分离关注点和可用性。控制器应该关注数据流和业务逻辑,而不是接口操作。理想情况下,您的指令应该是为可用性而编写的(比如这里的
fadey
——ed.注意:我不会称之为fadey;)。

本文中显示的代码对我理解relationship controller-指令非常有帮助,但它抛出了一个js错误

TypeError: Object function (scope) {
  $scope.items.splice(idx, 1);
  console.log($scope.items)
} has no method '$apply'
我已经稍微更新了指令,现在它对我有效:

function MyCtrl($scope) {
    $scope.items = [0, 1, 2, 3, 4, 5];

    $scope.clearItem = function(item) {
        var idx = $scope.items.indexOf(item);
        if (idx !== -1) {
            //injected into repeater scope by fadey directive
            this.destroy(function(scope) {

                $scope.items.splice(idx, 1);

                //this now shows the expected results
                console.log($scope.items)
            });
        }
    };
}

myApp.directive('fadey', function() {
    return {
        restrict: 'A', // restricts the use of the directive (use it as an attribute)
        // fires when the element is created and is linked to the scope of the parent controller
        link: function(scope, elm, attrs) { 
            var duration = parseInt(attrs.fadey);
            if (isNaN(duration)) {
                duration = 500;
            }
            elm = jQuery(elm);
            elm.hide();
            elm.fadeIn(duration)

            scope.destroy = function(complete) {
                elm.fadeOut(duration, function() {
                    scope.$apply(function() {
                        //note the change here 
                        complete(scope);
                    });
                });
            };
        }
    };
});

在角度控制器中没有正确的方法进行DOM操作。这就是指令的作用。请参阅。如果使用jQuery,请将其包含在angular.js之前,以便angular随后采用完整的jQuery库,而不是它自己的库。通过这样做,指令中的
elm
已经是一个jQuery对象,不必将其包装在
jQuery(elm)
中,我使用console.log(这)在第10行中,它表示这是一个“子”对象。为什么?这个类是什么?这一切似乎都很好,但是我的原始示例包括一个Object.delete success回调,其中
this
不再引用单击的元素,因此我不确定需要调用哪个对象
destroy()
?(还有,抱歉,我过早地接受了答案,直到我意识到它似乎没有涵盖上面的例子)@AladdinHoms在这种情况下,我相信这是ng repeat中存在的范围(其中提供了物品和销毁功能)。实际上这里有一点问题,似乎拼接不会影响控制器的原始$scope。如果我像您一样从我的答案中省略了
remove()
,那么LI仍然存在于DOM中,尽管它被
fadeOut()隐藏了。因此,诸如
  • 之类的“空”行不会触发任何项目,因为尽管有拼接,
    项目
    仍然具有长度。
    var myApp = angular.module('myApp', []);
    
    //myApp.directive('myDirective', function() {});
    //myApp.factory('myService', function() {});
    
    function MyCtrl($scope) {
        $scope.items = [0, 1, 2];
    
        $scope.clearItem = function(item) {
            var idx = $scope.items.indexOf(item);
            if (idx !== -1) {
                //injected into repeater scope by fadey directive
                this.destroy(function() {
                    $scope.items.splice(idx, 1);
                });
            }
        };
    }
    
    myApp.directive('fadey', function() {
        return {
            restrict: 'A', // restricts the use of the directive (use it as an attribute)
            link: function(scope, elm, attrs) { // fires when the element is created and is linked to the scope of the parent controller
                var duration = parseInt(attrs.fadey);
                if (isNaN(duration)) {
                    duration = 500;
                }
                elm = jQuery(elm);
                elm.hide();
                elm.fadeIn(duration)
    
                scope.destroy = function(complete) {
                    elm.fadeOut(duration, function() {
                        scope.$apply(function() {
                            complete.$apply(scope);
                        });
                    });
                };
            }
        };
    });
    
    TypeError: Object function (scope) {
      $scope.items.splice(idx, 1);
      console.log($scope.items)
    } has no method '$apply'
    
    function MyCtrl($scope) {
        $scope.items = [0, 1, 2, 3, 4, 5];
    
        $scope.clearItem = function(item) {
            var idx = $scope.items.indexOf(item);
            if (idx !== -1) {
                //injected into repeater scope by fadey directive
                this.destroy(function(scope) {
    
                    $scope.items.splice(idx, 1);
    
                    //this now shows the expected results
                    console.log($scope.items)
                });
            }
        };
    }
    
    myApp.directive('fadey', function() {
        return {
            restrict: 'A', // restricts the use of the directive (use it as an attribute)
            // fires when the element is created and is linked to the scope of the parent controller
            link: function(scope, elm, attrs) { 
                var duration = parseInt(attrs.fadey);
                if (isNaN(duration)) {
                    duration = 500;
                }
                elm = jQuery(elm);
                elm.hide();
                elm.fadeIn(duration)
    
                scope.destroy = function(complete) {
                    elm.fadeOut(duration, function() {
                        scope.$apply(function() {
                            //note the change here 
                            complete(scope);
                        });
                    });
                };
            }
        };
    });