Несколько селекторов или несколько функций - какой выигрыш в эффективности? - PullRequest
9 голосов
/ 30 июля 2010

Мне интересно, возможно ли сделать следующий код более кратким:

 $('#americasTrigger').hover(
  function () {
          $('#americasImg').fadeIn()
      },
  function(){
          $('#americasImg').fadeOut()
  }
  );

$('#europeTrigger').hover(
  function () {
      $('#europeImg').fadeIn();
  },
  function(){
      $('#europeImg').fadeOut();
  }
  );    

$('#middleEastTrigger').hover(
  function () {
      $('#middleEastImg').fadeIn();
  },
  function(){
      $('#middleEastImg').fadeOut();
  }
  );    

//More etc

Название страны остается одинаковым для каждого, с добавлением «Trigger» или «Img» в конце. Здесь много повторений, которые указывают мне, что я не пойду этим лучшим способом.

У меня были мысли вокруг:

  • Создание сценария кейса или
  • Каким-то образом получить селектор, используемый для выбора, сделать его строкой, разделить его имя, чтобы захватить используемую страну, и применить его к вложенной функции fadeIn / Out с «Img» в конце.

Это возможно, или я слишком фантазирую?

Редактировать 1: Большое спасибо за все ответы, извинения за то, что не опубликовали HTML, я поставил это ниже. Короче говоря, я использую карты изображений поверх bg-изображения (земли) в качестве триггера при наведении на изображение для плавного наложения моих абсолютно позиционированных изображений при наведении.

<div class="mapTub"> 

  <img src="images/transparentPixel.png" class="mapCover" usemap="#worldMap" width="524px" height="273px"/>

  <map name="worldMap" id="worldMap">
    <area id="americasTrigger" shape="poly" coords="1,2,3" href="#americas" />
    <area id="europeTrigger" shape="poly" coords="4,5,6" href="#europe" />
    <area id="middleEastTrigger" shape="poly" coords="7,8,9" href="#middleEast" />
  </map>

<img src="images/International_americas_dark.png" class="americas" id="americasImg" />
<img src="images/International_europe_dark.png" class="europe" id="europeImg" />
<img src="images/International_middleEast_dark.png" class="middleEast" id="middleEastImg"  />

</div>

Ответ Рейгеля выглядит как путь сюда, попробуйте еще раз сообщить об этом, дальнейшие комментарии приветствуются! :)

Ответы [ 4 ]

2 голосов
/ 30 июля 2010

Поскольку, похоже, вы получаете доступ только к unique ids, ваш лучший выбор - использовать lookup table IMO.

var lookmeup = [  [$('#americasTrigger'), $('#americasImg')],
                  [$('#europeTrigger'), $('#europeImg')],
                  [$('#middleEastTrigger'), $('#middleEastImg')]
               ];

$.each(lookmeup, function(index, element){
    element[0].hover(function(){
      element[1].fadeIn();
    }, function(){ 
      element[1].fadeOut();
    });
});

DRY!все готово!

Еще один способ сделать это более эффективно - использовать event delegation.

Если все ваши элементы hover имеют одинаковые TAGэтот подход может быть полезен:

$(document.body).delegate('div', 'mouseenter', function(e){
     $('#' + e.target.id.replace(/Trigger/, 'Img')).fadeIn();
});

$(document.body).delegate('div', 'mouseleave', function(e){
     $('#' + e.target.id.replace(/Trigger/, 'Img')).fadeOut();
});

Предполагая, что все ваши элементы "hoverable" были DIV с.Вы все равно должны присвоить этим элементам classname, чтобы нацеливались только эти конкретные элементы.

Имеет смысл ограничить root element для delegate().Здесь я использую document.body, который .live() делает.Самое замечательное в .delegate() заключается в том, что если ваши элементы наведения используют один родительский узел, вы можете применить delegate() к этому узлу.Таким образом вы уменьшаете число обработчиков событий, связанных

(2 вместо 6).

2 голосов
/ 30 июля 2010

Я, без знания html, предлагаю это ...

$('#americasTrigger, #europeTrigger, #middleEastTrigger').hover(
    function () {
        var id = this.id;
        $('#'+id.replace('Trigger', 'Img')).fadeIn();
        //$('#'+id.slice('0',id.indexOf('Trigger'))+'Img').fadeIn();
    },
    function(){
        var id = this.id;
        $('#'+id.replace('Trigger', 'Img')).fadeOut();
        //$('#'+id.slice('0',id.indexOf('Trigger'))+'Img').fadeOut();
    }
);

Вы также можете использовать .replace(), как предложено Anurag в комментарии ниже ...


id ='europeTrigger';
alert(id.slice('0',id.indexOf('Trigger'))); // alerts 'europe'
// '#'+id.slice('0',id.indexOf('Trigger'))+'Img' is '#europeImg'

демо

0 голосов
/ 30 июля 2010

Или, чтобы упростить задачу, добавьте класс маркера, например, называемый 'fadingImage', к каждому из изображений, а затем используйте этот код ...

$('.fadingImage').hover( 
    function () { 
        $(this).fadeIn() 
    }, 
    function(){ 
        $(this).fadeOut() 
    } 
); 

Это работает, потому что всеизображения, независимо от их идентификатора, обрабатываются одинаково, и все, что вам действительно нужно сделать, это определить, к каким изображениям на вашей странице должны быть прикреплены обработчики наведения, и это делается с помощью класса маркера.Вы даже можете вообще отказаться от идентификаторов, если они не используются ни для чего другого.

Обновление: Нет, я не проснулся (Спасибо jAndy & Reigel!)Я исправлю свой пост, чтобы учесть тот факт, что элемент, на который наведен курсор, не является тем, который исчезает.

Без какой-либо выборочной разметки, я собираюсь сделать некоторые предположения, нооригинальный постер может захотеть предоставить реальную разметку, чтобы поместить вещи в контекст.

<div>
    <span class="fadingTrigger">first text to hover over<span>
    <img class="fadingImage" src="..." alt="first image to be faded"/>
<div>
<div>
    <span class="fadingTrigger">second text to hover over<span>
    <img class="fadingImage" src="..." alt="second image to be faded"/>
<div>

$('.fadingTrigger').hover( 
    function () { 
        $(this).parent().find(".fadingImage").fadeIn() 
    }, 
    function(){ 
        $(this).parent().find(".fadingImage").fadeOut() 
    } 
); 

В зависимости от структуры разметки, метод поиска fadingImage, который связан с fadingTrigger, может варьироваться, но имея некоторую четко определенную структуру, она должна быть надежной.

Причина, по которой я бы предпочел этот метод, а не использование массива идентификаторов для поиска элементов, заключается в том, что любые добавления в разметку потребуют изменений вJavaScript - это было бы особенно проблематично, если разметка генерируется динамически.Javascript может также генерироваться динамически, чтобы включать соответствующий массив значений, но это нарушит принцип DRY.

0 голосов
/ 30 июля 2010

lol, похоже, что он может быть примерно того же размера или длиннее, чем ваш код, но определенно суше.

Спасибо @Andy за указание на снижение производительности в предыдущей версии с использованием $(..).each.

var regions = ['americas', 'europe', 'middleEast'];

$.each(regions, function(region) {
    var trigger = id(region, 'Trigger');
    var image = id(region, 'Image');

    $(trigger).hover(
        effect(image, 'fadeIn'),
        effect(image, 'fadeOut'),
    );
});

function effect(selector, method) {
    return function() {
        $(selector)[method]();
    };
}

function id(prefix, suffix) {
    return '#' + prefix + suffix;
}

Если вы можете изменить HTML, я бы закодировал все знания в самой странице и просто использовал jQuery для настройки событий при наведении.

<div class='trigger' data-image='#americasImg'>
   ..
</div>
<div class='trigger' data-image='#europeImg'>
  ..
</div>

1010 * Javascript *

function imageId(elem) {
    return $(elem).attr('data-image');
}

// Using the fade function from before
$('.trigger').hover(
    effect(imageId(this), 'fadeIn'),
    effect(imageId(this), 'fadeOut')
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...