AngularJs:当存在“;全球”;
AngularJs : what is the best way to changing DOM elements when there are "global"?
我来自JQuery,使用AngularJs的第一步让我有点困惑。。。
我的案例:
我有一个面板(#floatingpanel),它用css(顶部:-50px)隐藏在视口之外
我在应用程序的最深处有一个链接(a.trigger),当你点击该链接时;顶部";我的面板的属性从"-50px";至";0px";以使其可见(单击以切换可见性)。面板就在我页面主容器的这一端,但链接在数百个其他div
中。
让我们看看DOM结构:
<body>
<div class="main-wrapper" ng-app="myapp">
<div class="app">
<div class="many-things">
[...]
<a href="#" class="trigger" ng-click="toggleMyPanelVisibility()">
Click here to see the panel
</a>
[...]
</div>
</div><!-- .app -->
<div id="floatingpanel">
Hey ! I was hidden !
</div>
</div> <!-- #mainwrapper -->
</body>
在jQuery中,它将是:
$('a.trigger').click( function(e) {
e.preventDefault();
var el = $('#floatingpanel');
var top = el.css('top');
if (top<0) el.css('top', 0);
else el.css('top', -50);
});
我该如何与AngularJs合作
我会这样做:
var app = angular.module('myapp');
app.run(["$rootScope", function($rootScope) {
// Toggle du myaccountpanel
$rootScope.floatingpanelVisibility = false;
$rootScope.toggleMyPanelVisibility = function() {
$rootScope.floatingpanelVisibility = !$rootScope.floatingpanelVisibility;
var panel = angular.element( $('#floatingpanel') );
var top = -50;
if ($rootScope.floatingpanelVisibility)
top = 0;
panel.css({'top': top });
}
});
好的,它有效,但是。。。我想如果我继续这样下去,我的app.run
很快就会过载,不是吗?我也可以用我的";主包装器";但这太愚蠢了,它已经是我的应用范围了!
如何使用指令进行操作
什么可能是";最佳方式";来解决那个烂摊子
我在Angular中看到的两种最常见的方法是通过rootscope消息传递或通过服务。服务是两者中比较干净/比较好的。
公认的答案假设所有东西都在同一个控制器下,而这显然不是构建OP所描述内容的方式。
想象一下,一个页面由一堆小部件组成,这些小部件要么是子视图,要么是指令,都由它们自己的、独立的控制器处理。这是处理OP在Angular中所描述的"所有这些东西"的正确方法。
现在,您需要一种方法来触发一个可以由任何其他人响应的事件。如果您定义了一个服务,比如"pageEventService",它公开了一个启动/触发事件"togglePanel"的函数,以及一个保持状态的属性"panelIsVisible",那么您可以在需要触发事件的任何位置引用该服务,并在Panel中引用它来响应值。
.controller('SomeControllerThatCanTriggerEvent', function(pageEventService) {
var model = this;
model.togglePanel = pageEventService.togglePanel;
});
在该控制器控制的标记中的某个位置。。。
<a ng-click="model.togglePanel()">Toggle the Panel</a>
在面板控制器中。。。
.controller('PanelController', function(pageEventService) {
var model = this;
model.panelIsVisible = pageEventService.panelIsVisible;
});
以及在面板标记中。。。
<div id="TheAlmightyPanel" ng-show="model.panelIsVisible">... cool stuff here ...</div>
这比rootscope消息传递更干净,因为您可以明确pageEventService可以做什么以及谁引用它。您可以在视图、子视图和指令中使用它-无论您需要它。
你正在做的事情可以在不接触DOM的情况下完成,使用内置的角度指令本身,这里我只是使用ng-show
指令,如果你想把特定的类放在它上面,那么也可以使用ng-class
,任何动画都可以作为css动画提供,并且随着ngAnimate
模块的加入,可以更好地使用添加的类名来提供动画行为。
示例:-
<div class="main-wrapper" ng-app="myapp">
<div ng-controller="panelController as panel">
<a href="#" class="trigger" ng-click="panel.toggle($event)">Click here to see the panel</a>
<div ng-show="panel.show" class='panel'>
<!-- <div ng-class="{'show':panel.show}"> and define css rules for panel.show-->
Hey ! I was hidden !
</div>
</div>
</div>
在控制器panelController
中
angular.module('app').controller('panelController', function($scope){
var vm = this;
vm.show = false;
this.toggle = function($event){
$event.preventDefault();
vm.show = !vm.show;
}
});
我在这里只是使用controllerAs语法,如果你愿意,你也可以使用$scope,甚至可以将其转换为指令。
根据您的问题更新进行编辑:
创建一个控制器并在需要时使用内置的角度指令,而不是在真正不需要时使用jquery/手动dom操作,这并没有什么不好的。
<body>
<div class="main-wrapper" ng-app="myapp" ng-controller="mainController as main">
<div class="app">
<div class="many-things">
[...]
<a href="#" class="trigger" ng-click="main.togglePanel($event)">Click here to see the panel</a>
[...]
</div>
</div><!-- .app -->
<div id="floatingpanel" ng-show="panel.show">
Hey ! I was hidden !
</div>
</div> <!-- #mainwrapper -->
</body>
这可能是一个糟糕的答案,因为你似乎在考虑不创建控制器或重新设计视图。
.directive('togglePanel', function(jQuery){
return {
restrict: 'A',
link:function(scope, elm, attr){
elm.on('click', handleToggle);
scope.$on('$destroy', function(){
elm.off('click', handleToggle);
});
function handleToggle(e){
var $target = jQuery(attr.togglePanel);//Get the target
//Do what you want to do with the target
}
}
}
}).constant('jQuery', window.jQuery);
并将其用作:
<a href="#" class="trigger" toggle-panel="#floatingPanel">Click here to see the panel</a>
好!多亏了@PSL,我明白了,如果我在ng应用程序元素上设置控制器,这不是问题。
<div class="main-wrapper" ng-app="myapp" ng-controller="mainController as main">
我认为这是一个糟糕的做法
有了这个"主控制器",我可以很容易地与我的两个元素交互:通过ng-click
与链接交互,通过ng-class
(或ng-show
等)与面板交互我想不出更好的方法了。如果我避开这个"mainController",我可以发出指令,但要触摸我的面板,它会迫使我访问范围之外的DOM。。。
我肯定要把我的想法从jquery的方式改为angular的方式(这个链接会有所帮助)。
- Javascript-如何读取json文件中的列并将其保存在Javascript数组中
- 如果使用 lodash 将属性存在于另一个对象中,则向对象添加属性
- Jquery菜单操作不稳定,定位不正确,存在一般错误
- 如何使用Spring MVC将Facebook返回的响应数据保存在Java类中
- 用于检查数组中是否存在元素的javascript自定义方法
- 未捕获的类型错误:无法读取属性'name'即使它存在,也无法定义
- 正在将事件处理程序添加到不存在的类
- 是否存在React Native“;WEB代码安全防护”;
- 一个密码测试程序,如果存在空格,它会提醒用户
- 验证会话中是否存在对象's数组
- javascript如果图像不存在don't加载它
- 如何查找值是否存在于二叉树中
- IE9的HTML5 Canvas getImageData()函数存在问题
- 由于响应中不存在“Access Control Allow Origin”标头,跨域请求停止工作
- CORS-服务器端cookie没有保存在chrome浏览器上
- 检查是否存在使用chrome扩展的javascript库
- 是否存在Javascript Liferay Service库的文档?如何处理错误情况
- 测试mongo脚本中是否存在参数
- 存在每个时间元素的javascript事件
- AngularJs:当存在“;全球”;