gpt4 book ai didi

javascript - 从 Controller 中触发 jQuery DOM 操作的正确方法是什么?

转载 作者:数据小太阳 更新时间:2023-10-29 04:37:11 26 4
gpt4 key购买 nike

所以我一直在读到从 Controller 中进行 jQuery 操作是不好的做法,但我不清楚原因或如何纠正。

下面是 Youtube 教程中的代码,即使是视频创作者也评论说这是个坏主意,但没有解释原因并继续使用这种不良行为。

来自 https://www.youtube.com/watch?v=ilCH2Euobz0#t=553s :

$scope.delete = function() {
var id = this.todo.Id;
Todo.delete({id: id}, function() {
$('todo_' + id).fadeOut();
});
};

解决方案:

根据下面 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,因此我不再使用不再相关的 this '将点击的元素存储在 thisElem 中。

更新 2:

进一步更新了我的解决方案,以反射(reflect) funcComplete 实际上并未修改原始 $scope。

最佳答案

Angular 处理这个问题的方法是通过一个指令。我找到了一个完美的例子来涵盖你在下面提出的问题,尽管它不像我想要的那么干净。这个想法是您创建一个用作 HTML 属性的指令。当元素绑定(bind)到 Controller 的范围时,将触发 link 函数。该函数使元素淡入(完全可选)并公开一个销毁方法供您的 Controller 稍后调用。

更新:根据评论修改以实际影响范围。对解决方案并不满意,甚至更糟糕,因为原作者在他的 destroy 回调中调用了 complete.apply(scope),但没有在回调函数中使用 this .

更新 2:由于指令是使回调异步的指令,因此在此处使用 scope.$apply 可能是一个更好的主意,但请记住,如果您曾经使用过,那可能会变得很奇怪指令中的隔离范围。

http://jsfiddle.net/langdonx/K4Kx8/114/

HTML:

<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in items" fadey="500">
{{item}}
<a ng-click="clearItem(item)">X</a>
</li>
</ul>
<hr />
<button ng-click="items.push(items.length)">Add Item</button>
</div>

JavaScript:

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);
});
});
};
}
};
});

至于为什么,我认为这只是为了关注点分离和可用性。您的 Controller 应该关注数据流和业务逻辑,而不是界面操作。理想情况下,你的指令应该是为了可用性而编写的(就像这里的 fadey 一样——编者注:我不会称它为 fadey ;))。

关于javascript - 从 Controller 中触发 jQuery DOM 操作的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15744630/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com