Javascript 隐藏10000个下拉菜单的最佳方法

Javascript 隐藏10000个下拉菜单的最佳方法,javascript,jquery,css,backbone.js,drop-down-menu,Javascript,Jquery,Css,Backbone.js,Drop Down Menu,上下文- 我有一个聊天组件,每个聊天信息都有一个下拉列表 点击“更多选项图标”(3点)打开下拉菜单 每个聊天信息都是一个“主干项目视图” 一种解决方案是,单击“body”,遍历所有菜单,然后通过删除下拉菜单上的类来关闭下拉菜单 $("body").on("click", function() { $(".drop-down-menu").each(function(idx, item) { $(item).removeClass("open"); // open class i

上下文-

我有一个聊天组件,每个聊天信息都有一个下拉列表

点击“更多选项图标”(3点)打开下拉菜单

每个聊天信息都是一个“主干项目视图”

一种解决方案是,单击“body”,遍历所有菜单,然后通过删除下拉菜单上的类来关闭下拉菜单

$("body").on("click", function() {
  $(".drop-down-menu").each(function(idx, item) {
      $(item).removeClass("open"); // open class indicated it is open via CSS
  });
});
CSS-

.drop-down-menu {
    visibility: hidden;
    opacity: 0;
    &.open {
       opacity: 1;
       visibility: visible;
    }
}
如果有10000条或更多的消息,会对性能产生影响吗

因此,如果用户单击屏幕上的任何位置,我正在寻找隐藏下拉列表的最佳解决方案。
谢谢。

因为您一次只能打开一个下拉菜单,所以您可以保留一个指向它所附加的元素或元素索引的指针,而不是在所有菜单中循环。

您可以进行一些琐碎的更改,以提高代码的性能。第一件事是没有理由像你现在这样循环。jQuery对象是集合,jQuery操作通常在jQuery对象的元素上循环。因此:

$("body").on("click", function() {
  $(".drop-down-menu").removeClass("open");
});
这将自动从选择器
”匹配的所有元素中删除类
open
。下拉菜单“
。jQuery仍然会在内部进行循环,但是让jQuery自己迭代比让
更快。每个
调用您自己的回调,然后在回调中创建一个新的jQuery对象,在该对象上调用
。removeClass

此外,从逻辑上讲,从没有此类的元素中删除
open
类是毫无意义的。因此,您可以将操作范围缩小到只有删除
open
才有意义的元素:

$("body").on("click", function() {
  $(".drop-down-menu.open").removeClass("open");
});
这些原则广泛适用,实施成本很低。除此之外的任何优化都可能有缺点,应该通过实际分析代码来支持。您可以用只使用stockdom调用的代码替换jQuery代码,但是如果您需要对旧浏览器的支持,那么处理这个和那个怪癖的成本可能不值得。如果您使用的是stock DOM方法,那么可能会有不同的方法以代码复杂度为代价来提高不同的性能。

提供了一个快速修复高效jQuery选择器的方法

从长远来看,我建议将每条消息设置为
MessageView
组件,其中包含
ContextMenuView
组件。这样,每个视图只需要处理一个菜单

捕捉元素外部的单击 然后,使用以下
单击外部
视图作为关联菜单基本视图。它看起来很复杂,但它仅包装
模糊
聚焦
DOM事件,以了解您是否在视图外单击

它为视图本身提供了一个简单的
onClickOutside
回调,并在元素上触发了一个
click:outside
事件

菜单视图现在只需实现以下功能:

var ContextMenuView = ClickOutside.extend({
    toggle: function(val) {
        this.$el.toggleClass("open", val);
        this.focus(); // little requirement
    },
    // here's where the magic happens!
    onClickOutside: function() {
        this.$el.removeClass("open");
    }
});
请看演示

var-app={};
(功能(){
var$body=Backbone.$(document.body);
/**
*主干视图mixin,使视图能够捕获模拟
*通过跟踪
*鼠标移动并聚焦元素。
*
*附加信息:由于模糊事件是在鼠标上触发的
*按下按钮并在释放鼠标按钮时触发单击,则
*首先调用blur回调函数,然后侦听
*主体来触发模拟的外部单击。
*/
var ClickOutside=app.ClickOutside=Backbone.View.extend({
活动:{
“鼠标离开”:“鼠标离开”,
“鼠标输入”:“鼠标输入”,
“模糊”:“模糊”,
},
/**
*覆盖默认构造函数以扩展事件。
*/
构造函数:函数(){
this.mouseInside=false;
var proto=ClickOutside.prototype;
this.events=\ u0.extend({},proto.events,this.events);
单击外部.super.constructor.apply(这是参数);
this.clickOnceEventName='click.once'+this.cid;
},
/**
*劫持此私有方法以确保元素具有
*tabindex属性,可以使用。
*/
_setElement:函数(el){
单击外部。超级。设置元素。应用(此为参数);
var focusEl=this.focusEl;
if(focusEl&!this.$focusElem){
这。$focusElem=focusEl;
if(!(主干的焦点实例。$)){
这。$focusElem=主干。$(focusEl);
}
}否则{
this.$focusElem=this.$el;
}
这是.$focusElem.attr('tabindex',-1);
},
焦点:函数(){
这是。$focusElem.focus();
},
unfocus:function(){
这个。$focusElem.blur();
$body.off(this.clickOnceEventName);
},
isMouseInside:function(){
返回此mouseInside;
},
////////////////////////////
//私有事件处理程序//
////////////////////////////
onclickout:uu.noop,
_onClickOutside:函数(e){
本条第(e)款;
此.focusElem.trigger(“单击:外部”,e);
},
_onBlur:函数(e){
var$focusElem=这个。$focusElem;
如果(!this.ismouseinder()&&$focusElem.is(':visible')){
$body.one(this.clickOnceEventName,this.\onClickOutside.bind(this));
}否则{
$focusElem.focus();//重新聚焦内部单击
}
},
_onMouseCenter:函数(e){
this.mouseInside=true;
},
_onMouseLeave:函数(e){
this.mouseInside=false;
},
});
var DropdownView=app.Dropdown=ClickOutside.extend({
切换:功能(val){
此.$el.开关(val);
这是focus();
},
onClickOutside:function(){
这个。$el.hide();
}
});
})();
var DemoView=Backbone.View.extend({
类名:“演示视图”,
模板:$(“#de