2012-06-23 2 views
2

Я работаю над простым интерфейсом на стороне клиента, где у меня есть объект jQuery, к которому я хочу получить доступ непосредственно при нажатии на гиперссылку. Упрощенный код:Доступ к объекту javascript непосредственно через DOM, проходящий через jQuery

<div class="controls"> 
    <div class="score"> 
     <a class="button" href="/add">Add points!</a> 
    </div> 
</div> 


$(".controls").myControls(); 

$.fn.myControls = function() { 
    return $.extend(this, $.myControls).initialize(); 
} 

$.myControls = { 
    initialize: function() { 
     this.scoreElement = $("div.score", this); 
     this.linkElement = $("a", this.scoreElement); 

     this.scoreElement.score = 0; 

     var _this = this; 
     this.linkElement.click(function() { 
      _this.clickHandler(this); 
     }); 
    }, 
    clickHandler: function(element) { 
     var scoreElement = $(element).parent(); 
     scoreElement.score = 1; 
    } 
} 

Пояснение: .controls элемент имеет .score элемент, который удваивает в качестве контейнера для информации (оценка this.scoreElement.score). Когда я нажимаю ссылку в элементе .score, я нахожу родительский элемент, который является тем же самым элементом в DOM, что и this.scoreElement, и попытайтесь установить его свойство score на 1. Очевидно, что это не сработает, так как местное свойство scoreElement.score в методе clickHandler «не определено».

Так вот мой вопрос: есть простой способ получить доступ к моему this.scoreElement объекту непосредственно через обход DOM с JQuery?

Обязательно могу проверить, this.scoreElement == $(element).parent() в некотором роде, а затем получить доступ к объекту недвижимости в моем this.scoreElement объекте, но прямой доступ будет более изящным и надежным. Это возможно? Неужели я ошибаюсь? Благодаря!

PS: Игнорируйте тот факт, что я использую parent(), чтобы найти scoreElement, я использую его только для иллюстрации моей проблемы. Если это не является частью проблемы, в этом случае не игнорируйте :)

+0

Это все очень запутанным. Чего вы на самом деле пытаетесь достичь? –

+0

То, что я на самом деле собираю, это простая игра в кости, в которой я могу «держать» любую смерть, щелкнув ссылку, связанную с фильмом; эта ссылка является дочерним элементом элемента DOM, который составляет матрицу. Я думаю, мне лучше создать отдельный объект для каждой кубики, что заставляет мою проблему уйти, но мне все же хотелось бы немного узнать, получив хорошее решение/ответ на мой вопрос. – Phortuin

ответ

3

Хотя это, конечно, можно использовать свой собственный «контроль-объект», чтобы сохранить соответствующие данные, обычно я предпочитаю полагаться на JQuery это делать - с .data() способом, как это:

$(this.scoreElement).data('score', 0); // in initialize() 
$(this).parent().data('score', 1); // in clickHandler() 

Этот подход позволяет мне масштабироваться более легко, так как мне никогда не нужно бояться «перекрывающихся» проблем, используя единственный объект «control», а не объект для элемента.

+0

Хорошо, это будет работать и звучит как прочное решение, но, к сожалению, менее читаемо. Можете ли вы сделать аргумент для аргумента «масштабирования», возможно, простого примера? Благодаря! – Phortuin

1

Я бы подумал, что если вы использовали прокси-функцию jQuery для вашего обработчика кликов, вы могли бы просто пойти this.scoreElement внутри clickHandler, и вы бы даже не нужно пересекать DOM. Как это:

$.myControls = { 
    initialize: function() { 
     this.scoreElement = $("div.score", this); 
     this.linkElement = $("a", this.scoreElement); 

     this.scoreElement.score = 0; 

     this.linkElement.click($.proxy(this.clickHandler, this)); 
    }, 
    clickHandler: function(event) { 
     var element = event.target; 
     this.scoreElement.score = 1; 
    } 
} 
+0

Это было бы отличным ответом, но (возможно, я не был полностью ясен в своем вопросе) 'this.scoreElement' - это не только один элемент, но он относится к ссылке, которая была нажата. Таким образом, «event.target» (элемент ссылки) должен указывать на «его» «scoreElement», что является моей проблемой: где работает этот 'scoreElement' и как я могу получить к нему доступ напрямую? Ваш ответ решает только мою проблему, если 'this.scoreElement' - это единственный объект, существующий в' .myControls'. Но спасибо в любом случае :) – Phortuin

1

После прогрессивного упрощения (и сохранения оценки несколько иначе) я получаю код ниже, в котором scoreElement обнаружен один раз в .controls div, а затем удерживается в закрытии, чтобы сделать его доступным для соответствующего обработчика кликов. Вы также можете использовать .closest() - см. Прокомментированную строку.

$.fn.myControls = function() { 
    return this.each(function() { 
     var scoreElement = $("div.score", $(this)); 
     scoreElement.data('score', 0); 
     $("a", scoreElement).on('click', function() { 
      scoreElement.data('score', 1);//get scoreElement from closure formed by the outer "each" function. 
      //$(this).closest(".score").data('score', 1);//alternative to the line above, not requiring closure. 
     }); 
    }); 
}; 

вызова, как и в вопросе с:

$(".controls").myControls();  

Это так тривиально и одномерно это на самом деле не гарантирует, в своем собственном праве, плагин JQuery. Если не было какой-то веская причина для плагина (., Например, повторное использование или необходимость близкородственных методов), то я бы фразу она следующим образом:

$(".controls").each(function() { 
    var scoreElement = $("div.score", $(this)); 
    scoreElement.data('score', 0); 
    $("a", scoreElement).on('click', function() { 
     scoreElement.data('score', 1);//get scoreElement from closure formed by the outer "each" function. 
     //$(this).closest(".score").data('score', 1);//alternative to line above, not requiring closure. 
    }); 
}); 

Это тот же самый код с плагином обертке удален и прикреплен непосредственно к тот же базовый объект jQuery.

И если вы действительно хотите, вы можете написать все это в три строки следующим образом:

$(".controls").find("div.score").data('score', 0).find("a.button").on('click', function() { 
    $(this).closest(".score").data('score', 1); 
}); 
+0

Спасибо! Я согласен со всем, что вы говорите, ядром решения здесь является метод '.data()' jQuery, который также утверждал raina77ow. Я пойду с его ответом, если вы не возражаете. Конечно, мой фактический код немного сложнее, чем то, что я написал здесь в качестве примера, но вы хорошо понимаете, что этот конкретный бит не гарантирует плагин. Но опять же, это делает код более читабельным и масштабируемым. – Phortuin

Смежные вопросы