Разрешено ли использовать селектор jQuery $ (this) дважды в функции и в каждом включенном цикле? - PullRequest
0 голосов
/ 08 января 2019

У меня есть список, который содержит x столбцов данных. При нажатии кнопки редактирования в строке я хочу установить html-содержимое каждого столбца этой строки с атрибутом name в массив, ключ которого назван значением атрибутов name столбцов.

data['id']   = '123';
data['name'] = 'John Doe';
data['city'] = 'Arlington';

Для этого я запускаю событие щелчка на панели редактирования. Внутри этой функции я работаю с селектором $ (this) для настройки цикла each () для всех элементов, имеющих атрибут name. Внутри этого цикла я снова ловлю имена и значения каждого соответствующего элемента с помощью селектора $ (this).

Итак, мой вопрос: хотя это работает - разрешено ли это делать таким образом? Использование $ (this) для двух разных вещей внутри одной и той же функции? Есть ли другой способ?

Вот мой рабочий пример кода

$( document ).ready(function() {
    $(document).on( "click", ".edit", function() {
      var data = {};
      
      $(this).closest('.row').children('div[name]').each(function() {
        //form_data.append($(this).attr('name'), $(this).html());
        data[$(this).attr('name')] = $(this).html();
      });
      
      $('#result').html(JSON.stringify(data, null, 4));

    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="row">
<div name="id">123</div>
<div name="name">John Doe</div>
<div name="city">Berlin</div>
<div class="edit">> edit <</div>
</div>
<br clear="all">
<div id="result"></div>

Ответы [ 3 ]

0 голосов
/ 08 января 2019

в этом нет ничего плохого, то, что вы делаете, это просто

function setDivs() {
  //form_data.append($(this).attr('name'), $(this).html());
  data[$(this).attr('name')] = $(this).html();
}

function docClick(){
    var data = {};
    $(this).closest('.row').children('div[name]').each(setDivs);
    $('#result').html(JSON.stringify(data, null, 4));
}

function docReady(){
  $(document).on( "click", ".edit", docClick)
}

$( document ).ready(docReady);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="row">
<div name="id">123</div>
<div name="name">John Doe</div>
<div name="city">Berlin</div>
<div class="edit">> edit <</div>
</div>
<br clear="all">
<div id="result"></div>
0 голосов
/ 08 января 2019

Это разрешено?

Работает, конечно.

Зависит от того, что вы подразумеваете под «разрешено».

  • Это сбивает с толку - возможно.
  • Может ли это вызвать проблемы - определенно.

(Есть много вопросов о SO или проблемах, вызванных этим, которые подтверждают, что это вызывает проблемы).

Повторное использование имен переменных (в данном случае «this») является распространенным явлением и основано на scope .

Трудно сказать, есть ли у вас ошибка, потому что вы на самом деле хотели html ".edit" или attr ".edit", а не div, поэтому вы можете устранить эту путаницу, скопировав this в переменную :

$(document).on( "click", ".edit", function() {
  var data = {};
  var btn = $(this);  // the button that was clicked

  btn.closest('.row').children('div[name]').each(function() {

    // Do you mean the div or did you really mean the clicked button?
    data[$(this).attr('name')] = $(this).html();  

    var div = $(this);  // the child div

    // clearly not what is desired
    // `btn` variable referring to the outer `this`
    data[div.attr('name')] = btn.html();  

    // intention clear
    data[div.attr('name')] = div.html();  
  });

  $('#result').html(JSON.stringify(data, null, 4));

});

В данном случае это "ясно", поскольку вы не будете использовать btn html для всех записей данных (или не так ли? Я не знаю ваших требований ...). Так что "вряд ли".

Но легко увидеть, как в другом сценарии вы хотели бы сослаться на то, что было нажано btn==this внутри вложенного .each.

0 голосов
/ 08 января 2019

Попробуйте этот трюк:

$( document ).ready(function() {
    $(document).on( "click", ".edit", function() {
      var data = {};
      var that = this; // trick here
      $(this).closest('.row').children('div[name]').each(function() {
        //form_data.append($(this).attr('name'), $(this).html());
        data[$(this).attr('name')] = $(that).html();// replace this = that if you want to get parent element
      });

      $('#result').html(JSON.stringify(data, null, 4));

    });
});
...