AngularJS DOM修改删除事件->需要可行的变通方法实现模式
AngularJS DOM modification deletes events -> need viable workaround implementation schema
有人能向我解释一下在AngularJS中创建抵制DOM修改的自定义事件侦听器的正确方法吗?
我的问题是,我需要根据下拉菜单绘制2个不同的数据集。数据集的每个元素都必须响应一个事件(mouseover/mousemove等)。但当从一个数据集切换到另一个数据集中时,事件侦听器会丢失。这种行为在这里得到了很好的解释:
- 将HTML注入DOM会破坏AngularJS事件
但我不明白绕过它的答案。帖子提到手动避开ng应用程序可能会有所帮助,但这似乎是一个糟糕的解决方法。
我宁愿重新定义我自己的事件监听器,这样它们就不会在DOM修改过程中丢失。有人能告诉我如何在指令/控制器模型中正确使用addEventListener
吗?
这里有一个SSCCE html/javascript文件,它说明了我的程序是如何组织的
angular.module("testUpdate", [])
.directive("shape", function($parse) {
return {
restrict: "E",
replace: false,
scope: false,
link: function(scope, element, attrs) {
// draw dataset according to #shapeSelection choice
d3.select("#shapeSelection")
.on("change", scope.redraw);
// change color on mouseover
d3.selectAll("circle,rect,polygon")
.on("mouseover", function() {
d3.select(this).style("fill", "#0f0");
});
}
};
})
.controller("testController", function($scope) {
$scope.shape = "none";
//create datasets
$scope.dataset1 = [{
cx: 10,
cy: 20
}, {
cx: 30,
cy: 20
}];
$scope.dataset2 = [{
w: 20,
h: 20
}];
// the triangle actually responds to the event
d3.selectAll("svg")
.append("polygon")
.attr("points", "15,20 0,40 30,40")
.style("fill", "#f00");
// draw dataset depending on the user choice
$scope.draw = function() {
if ($scope.shape === "circle") {
d3.selectAll("svg").selectAll("circle")
.data($scope.dataset1).enter()
.append("circle")
.attr("cx", function(d) { return d.cx; })
.attr("cy", function(d) { return d.cy; })
.attr("r", 10)
.style("fill", "#f00");
}
else if ($scope.shape === "rect") {
d3.selectAll("svg").selectAll("rect")
.data($scope.dataset2).enter()
.append("rect")
.attr("width", function(d) { return d.w; })
.attr("height", function(d) { return d.h; })
.attr("x", 0)
.attr("y", 10)
.style("fill", "#f00");
}
else {}
}
// once removed is called, the event listener is destroyed
$scope.redraw = function() {
d3.selectAll("circle,rect,polygon").remove();
$scope.draw()
}
});
<script src="https://code.angularjs.org/1.2.15/angular.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<div ng-app="testUpdate" ng-controller="testController">
<select name="shapeSelector" ng-model="shape" id="shapeSelection">
<option value="none">--none--</option>
<option value="circle">dataset1</option>
<option value="rect">dataset2</option>
</select>
<shape id="shapeTag">
<svg id="shapeSVG" display="block"></svg>
</shape>
</div>
d3.selection.remove()
函数修改DOM并使事件侦听器无效,以便三角形正确响应,而不是圆形和矩形。
一个糟糕的解决方法是为两个数据集创建DOM,并将未选择的数据集的可见性设置为隐藏,但两个数据集中都很大,因此这不是一个可行的选项。
提前感谢
从代码中,您似乎只想在shape
指令内的元素上捕获mouseover
事件。
我认为对您来说,最好的解决方案是将事件处理程序与元素绑定的代码移动到$scope.redraw
或$scope.draw
函数中:
$scope.draw = function() {
if ($scope.shape === "circle") {
/* ... */
} else {}
// change color on mouseover
d3.selectAll("circle,rect,polygon")
.on("mouseover", function() {
d3.select(this).style("fill", "#0f0");
});
}
当您在D3land中操作DOM时,不应该依赖Angular的链接函数中定义的事件处理程序。在我编写的指令中,当数据更新时,我只在指令中使用$watch
来触发redraw
函数,就像使用change
函数一样。
替代解决方案
另一方面,如果您想处理指令中的事件(例如,如果您不必将d3
传递给$scope
),和如果您使用的是jQuery,则可以在具有正确selectors
的父级上使用.on
方法。请注意,jQlite
(Angular的jQuery内部实现)并不假定.on
具有selectors
。
在这种情况下,即使您更改了下面的DOM,也会在父级调用事件处理程序。如果希望访问与事件处理程序内的节点关联的data
,可以使用var data = d3.select(this).data()
。
- Node.js使用Series函数(模式?)实现流控制时出现意外结果
- json模式v4如何根据枚举实现枚举
- 为什么在javascript中的模块模式中实现Lazy函数时范围会发生变化
- 试图通过模块模式在DOM元素上实现change()事件
- 如何在严格模式下实现以下JavaScript闭包
- JavaScript的严格模式是如何实现的
- config.fullPage = true;在 ckEditor 内联模式下无法正常工作.如何实现这一点
- 设计模式以实现依赖于其他插件的插件
- 为什么在javascript中实现模块模式时要执行自我执行
- 如何在 JavaScript 中实现一个简单的优先级侦听器模式
- 为什么这个 ng-idle 实现不连接模式和样式
- 这种嵌套命名空间继承模式是否得到了很好的实现
- 是否有在 JavaScript 中实现自记忆函数的规范模式
- 如何使用公共静态实现模块模式
- Angularjs模式窗口在我的应用程序中的实现
- AngularJS DOM修改删除事件->需要可行的变通方法实现模式
- 为登录/注册模式实现正确的php数据库访问
- 如何实现JavaScript设计模式
- 如何实现命令模式而不是使用适配器
- 可以使用揭示模块模式实现Javascript类吗?