防止执行两个指令表达式
Prevent execution of two directive expressions
我有这个html
<nav ng-init="items = false">
<ul class="main-items">
<li><a ng-click="..."></a></li>
<li><a ng-click="..."></a></li>
...
<li><a ng-click="items = !items">More...</a></li>
</ul>
<ul class="more-items" ng-show="items" doc-mousedown="$parent.items = false">
<li><a ng-click="...">Item 1</a></li>
<li><a ng-click="...">Item 2</a></li>
...
</ul>
</nav>
这是做什么的:
.main-items
始终可见,当单击 更多... 时,它会切换 more-items
. 的显示
doc-click
是我自定义的简单指令,用于侦听文档 mousedown,它检查鼠标是否在 之外进行交互定义指令并执行提供的表达式的元素。在这种情况下,它隐藏了 .more-items
.
问题
单击 更多... link 有效并正确显示其他项目,但是当再次单击时,此元素在元素之外指令因此指令首先触发,然后 更多... link 上的 ngClick
显示其他项目,而不是仅仅隐藏它们...
我正在尝试解决这个问题,但我似乎无法解决这个问题。我想在 docMousedown
上使用 $event.preventDefault()
,但是 mousedown 和 click 是两个不共享事件对象的事件。 :(
你建议如何解决这个问题?
工作示例
DocDetectController.$inject = ["$scope", "$element", "$document"];
function DocDetectController($scope, $element, $document) {
var el = $element[0];
var self = this;
$document.on("mousedown.docDetect", function(evt) {
if (evt.target !== el && !$.contains(el, evt.target)) {
evt.preventDefault();
$scope.$apply(self.docDetect);
}
});
}
angular
.module("Test", [])
.directive("docDetect", function() {
return {
restrict: "A",
controller: DocDetectController,
controllerAs: "doc",
scope: true,
bindToController: {
docDetect: "&"
}
};
});
nav ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
user-select: none;
}
nav ul li {
margin: 0;
padding: 0;
}
nav ul li a {
text-decoration: none;
padding: .5rem 1rem;
background-color: #f4f4f4;
color: #000;
}
nav ul li a:hover {
background-color: #ddd;
}
nav.collapsed .more-items {
display: none;
}
hr {
height: 1px;
border: 0 none;
background-color: #ccc;
}
<section ng-app="Test">
<nav ng-class="{ collapsed: collapse }" ng-init="collapse = true">
<ul class="main-items">
<li><a href="">Link 1</a></li>
<li><a href="">Link 2</a></li>
<li><a href="">Link 3</a></li>
<li><a href="" ng-click="collapse = !collapse">More...</a></li>
</ul>
<hr>
<ul class="more-items" doc-detect="$parent.collapse = true">
<li><a href="">More 1</a></li>
<li><a href="">More 2</a></li>
<li><a href="">More 3</a></li>
<li><a href="">More 4</a></li>
<li><a href="">More 5</a></li>
</ul>
</nav>
</section>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
有一个简单的方法可以做到这一点你需要检查这个解决方案的目标
在你的 child 事件中,你只需要添加一个检查,你将确保如果目标是 parent 元素不会触发任何东西,在这种情况下你需要从它被触发的地方检查元素您可以在您的活动 object.
中获取这些详细信息
最简单的解决方案
是根据 $scope.items
值改变 更多... 行为的那个。
HTML 模板
<nav ng-init="items = false">
<ul class="main-items">
<li><a ng-click="..."></a></li>
<li><a ng-click="..."></a></li>
...
<!-- THIS IS THE CHANGE -->
<li ng-switch="!!items">
<a ng-switch-when="false" ng-click="items = !items">More...</a>
<a ng-switch-when="true" href="">More...</a>
</li>
</ul>
<ul class="more-items" ng-show="items" doc-mousedown="$parent.items = false">
<li><a ng-click="...">Item 1</a></li>
<li><a ng-click="...">Item 2</a></li>
...
</ul>
</nav>
DocDetectController.$inject = ["$scope", "$element", "$document"];
function DocDetectController($scope, $element, $document) {
var el = $element[0];
var self = this;
$document.on("mousedown.docDetect", function(evt) {
if (evt.target !== el && !$.contains(el, evt.target)) {
evt.preventDefault();
$scope.$apply(self.docDetect);
}
});
}
angular
.module("Test", [])
.directive("docDetect", function() {
return {
restrict: "A",
controller: DocDetectController,
controllerAs: "doc",
scope: true,
bindToController: {
docDetect: "&"
}
};
});
nav ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
user-select: none;
}
nav ul li {
margin: 0;
padding: 0;
}
nav ul li a {
text-decoration: none;
padding: .5rem 1rem;
background-color: #f4f4f4;
color: #000;
}
nav ul li a:hover {
background-color: #ddd;
}
nav.collapsed .more-items {
display: none;
}
hr {
height: 1px;
border: 0 none;
background-color: #ccc;
}
<section ng-app="Test">
<nav ng-class="{ collapsed: collapse }" ng-init="collapse = true">
<ul class="main-items">
<li><a href="">Link 1</a></li>
<li><a href="">Link 2</a></li>
<li><a href="">Link 3</a></li>
<li ng-switch="!!collapse">
<a ng-switch-when="true" href="" ng-click="$parent.collapse = !$parent.collapse">More...</a>
<a ng-switch-when="false" href="">More...</a>
</li>
</ul>
<hr>
<ul class="more-items" doc-detect="$parent.collapse = true">
<li><a href="">More 1</a></li>
<li><a href="">More 2</a></li>
<li><a href="">More 3</a></li>
<li><a href="">More 4</a></li>
<li><a href="">More 5</a></li>
</ul>
</nav>
</section>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
我有这个html
<nav ng-init="items = false">
<ul class="main-items">
<li><a ng-click="..."></a></li>
<li><a ng-click="..."></a></li>
...
<li><a ng-click="items = !items">More...</a></li>
</ul>
<ul class="more-items" ng-show="items" doc-mousedown="$parent.items = false">
<li><a ng-click="...">Item 1</a></li>
<li><a ng-click="...">Item 2</a></li>
...
</ul>
</nav>
这是做什么的:
.main-items
始终可见,当单击 更多... 时,它会切换more-items
. 的显示
doc-click
是我自定义的简单指令,用于侦听文档 mousedown,它检查鼠标是否在 之外进行交互定义指令并执行提供的表达式的元素。在这种情况下,它隐藏了.more-items
.
问题
单击 更多... link 有效并正确显示其他项目,但是当再次单击时,此元素在元素之外指令因此指令首先触发,然后 更多... link 上的 ngClick
显示其他项目,而不是仅仅隐藏它们...
我正在尝试解决这个问题,但我似乎无法解决这个问题。我想在 docMousedown
上使用 $event.preventDefault()
,但是 mousedown 和 click 是两个不共享事件对象的事件。 :(
你建议如何解决这个问题?
工作示例
DocDetectController.$inject = ["$scope", "$element", "$document"];
function DocDetectController($scope, $element, $document) {
var el = $element[0];
var self = this;
$document.on("mousedown.docDetect", function(evt) {
if (evt.target !== el && !$.contains(el, evt.target)) {
evt.preventDefault();
$scope.$apply(self.docDetect);
}
});
}
angular
.module("Test", [])
.directive("docDetect", function() {
return {
restrict: "A",
controller: DocDetectController,
controllerAs: "doc",
scope: true,
bindToController: {
docDetect: "&"
}
};
});
nav ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
user-select: none;
}
nav ul li {
margin: 0;
padding: 0;
}
nav ul li a {
text-decoration: none;
padding: .5rem 1rem;
background-color: #f4f4f4;
color: #000;
}
nav ul li a:hover {
background-color: #ddd;
}
nav.collapsed .more-items {
display: none;
}
hr {
height: 1px;
border: 0 none;
background-color: #ccc;
}
<section ng-app="Test">
<nav ng-class="{ collapsed: collapse }" ng-init="collapse = true">
<ul class="main-items">
<li><a href="">Link 1</a></li>
<li><a href="">Link 2</a></li>
<li><a href="">Link 3</a></li>
<li><a href="" ng-click="collapse = !collapse">More...</a></li>
</ul>
<hr>
<ul class="more-items" doc-detect="$parent.collapse = true">
<li><a href="">More 1</a></li>
<li><a href="">More 2</a></li>
<li><a href="">More 3</a></li>
<li><a href="">More 4</a></li>
<li><a href="">More 5</a></li>
</ul>
</nav>
</section>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
有一个简单的方法可以做到这一点你需要检查这个解决方案的目标 在你的 child 事件中,你只需要添加一个检查,你将确保如果目标是 parent 元素不会触发任何东西,在这种情况下你需要从它被触发的地方检查元素您可以在您的活动 object.
中获取这些详细信息最简单的解决方案
是根据 $scope.items
值改变 更多... 行为的那个。
HTML 模板
<nav ng-init="items = false">
<ul class="main-items">
<li><a ng-click="..."></a></li>
<li><a ng-click="..."></a></li>
...
<!-- THIS IS THE CHANGE -->
<li ng-switch="!!items">
<a ng-switch-when="false" ng-click="items = !items">More...</a>
<a ng-switch-when="true" href="">More...</a>
</li>
</ul>
<ul class="more-items" ng-show="items" doc-mousedown="$parent.items = false">
<li><a ng-click="...">Item 1</a></li>
<li><a ng-click="...">Item 2</a></li>
...
</ul>
</nav>
DocDetectController.$inject = ["$scope", "$element", "$document"];
function DocDetectController($scope, $element, $document) {
var el = $element[0];
var self = this;
$document.on("mousedown.docDetect", function(evt) {
if (evt.target !== el && !$.contains(el, evt.target)) {
evt.preventDefault();
$scope.$apply(self.docDetect);
}
});
}
angular
.module("Test", [])
.directive("docDetect", function() {
return {
restrict: "A",
controller: DocDetectController,
controllerAs: "doc",
scope: true,
bindToController: {
docDetect: "&"
}
};
});
nav ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
user-select: none;
}
nav ul li {
margin: 0;
padding: 0;
}
nav ul li a {
text-decoration: none;
padding: .5rem 1rem;
background-color: #f4f4f4;
color: #000;
}
nav ul li a:hover {
background-color: #ddd;
}
nav.collapsed .more-items {
display: none;
}
hr {
height: 1px;
border: 0 none;
background-color: #ccc;
}
<section ng-app="Test">
<nav ng-class="{ collapsed: collapse }" ng-init="collapse = true">
<ul class="main-items">
<li><a href="">Link 1</a></li>
<li><a href="">Link 2</a></li>
<li><a href="">Link 3</a></li>
<li ng-switch="!!collapse">
<a ng-switch-when="true" href="" ng-click="$parent.collapse = !$parent.collapse">More...</a>
<a ng-switch-when="false" href="">More...</a>
</li>
</ul>
<hr>
<ul class="more-items" doc-detect="$parent.collapse = true">
<li><a href="">More 1</a></li>
<li><a href="">More 2</a></li>
<li><a href="">More 3</a></li>
<li><a href="">More 4</a></li>
<li><a href="">More 5</a></li>
</ul>
</nav>
</section>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>