Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 06.05.2016, 16:15
Новичок на форуме
Отправить личное сообщение для chelfenix Посмотреть профиль Найти все сообщения от chelfenix
 
Регистрация: 10.04.2015
Сообщений: 7

контекст this
Здравствуйте. Столкнулся с проблемой непонимания this. Документация читал, но в ней мне многое непонятно.
Суть проблемы. Есть неопределенное количество элементов, по клику на один из них в дочерний элемент надо единожды вставить, например текст. Как сделал :
- родительские элементы обозначил классом,
- на класс повесил обработчик по click,
- контекст выполнения определяю по this,
- ищу в родителе элемент для вставки, вставляю текст.
- удаляю класс.
Мне казалось, что после удаления класса обработчик не будет больше работать для этого элемента, но класс удаляется, а клик по элементу продолжает вставлять текст.
Я что-то не понимаю, но не могу понять что) Объясните, пожалуйста, почему так происходит и как надо делать, чтобы такого не случалось.
Код посмотреть можно вот тут
https://jsfiddle.net/hgfpt97u/1/
Листинг ниже.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>


    <style>
        .item {
            height: 30px;
            width: 100px;
            margin-bottom: 20px;
            background: #cccccc;
        }
    </style>
</head>
<body>
<div class="item  click">
    <div class="item-click"></div>
</div>

<div class="item  click">
    <div class="item-click"></div>
</div>

<div class="item  click">
    <div class="item-click"></div>
</div>

<div class="item  click">
    <div class="item-click"></div>
</div>
<script>
    $('.click').click(function () {
        var item = $(this);
        item.find('.item-click').append('test');
        item.removeClass('click');
        console.log('test');
    })
</script>
</body>
</html>
Ответить с цитированием
  #2 (permalink)  
Старый 06.05.2016, 16:37
Профессор
Отправить личное сообщение для Decode Посмотреть профиль Найти все сообщения от Decode
 
Регистрация: 31.01.2015
Сообщений: 576

Так? https://jsfiddle.net/hgfpt97u/2/
Ответить с цитированием
  #3 (permalink)  
Старый 06.05.2016, 17:11
Новичок на форуме
Отправить личное сообщение для chelfenix Посмотреть профиль Найти все сообщения от chelfenix
 
Регистрация: 10.04.2015
Сообщений: 7

Да, так, большое вам спасибо. Всю ночь пытался сам разобраться, безуспешно.
Можно пояснить разницу между вашим решением и тем, что делал я?
Ответить с цитированием
  #4 (permalink)  
Старый 07.05.2016, 03:01
Профессор
Отправить личное сообщение для Decode Посмотреть профиль Найти все сообщения от Decode
 
Регистрация: 31.01.2015
Сообщений: 576

Сообщение от chelfenix
Можно пояснить разницу между вашим решением и тем, что делал я?
Разница в делегировании. Метод on реагирует на динамические изменения, а простой bind — нет.
Ответить с цитированием
  #5 (permalink)  
Старый 07.05.2016, 06:35
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Сообщение от Decode
Метод on реагирует на динамические изменения, а простой bind — нет.
Немного не так. Метод on появился в версии 1.7 и объединяет три ранних метода: .bind(), .delegate(), .live(). Этим методом можно также установить обработчик как и в .bind():

$('.click').on('click', function ()


или делегировать как в .delegate() (ваш код):

$('body').on('click', '.click', function()


причем делегировать естественно выгоднее ближайшему родителю существующему на странице.

Что собственно происходит и в .live(), если задан контекст, иначе вверх по дереву DOM... и это были проблемы JQ. )

Последний раз редактировалось laimas, 07.05.2016 в 06:41.
Ответить с цитированием
  #6 (permalink)  
Старый 07.05.2016, 22:21
Новичок на форуме
Отправить личное сообщение для chelfenix Посмотреть профиль Найти все сообщения от chelfenix
 
Регистрация: 10.04.2015
Сообщений: 7

Не уверен, что все правильно понял, но судя по всему при использовании метода .bind() в объект JQ пишется указатель на DOM элемент. Удаление селектора не приводит к потере указателя, на что я рассчитывал делая removeClass. То ли указатель перезаписывается, то ли он вообще представляет из себя не ссылку на селектор - этого я так и не понял.
Но суть в том, что обработчик все равно продолжит срабатывания при событии, а this будет иметь соответствующий контекст. Если это поведение нежелательно, то надо или .delegate() использовать, который видимо как-то по другому работает с указателями и тогда удаление класса сработает, или же прописывать $(this).unbind().

Печально, что эти моменты явно не прописаны в документации.
Большое вам спасибо, что помогли разобраться.
Ответить с цитированием
  #7 (permalink)  
Старый 08.05.2016, 01:45
Профессор
Отправить личное сообщение для Decode Посмотреть профиль Найти все сообщения от Decode
 
Регистрация: 31.01.2015
Сообщений: 576

chelfenix, при делегировании обработчик вешается на родительский элемент. И там уже проверяется класс (селектор твой), а он уже убран при первом клике, вот и не срабатывает.

А при bind просто на DOM узле висит обработчик. Соответственно его надо убирать при клике.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Контекст this в QML GayCoder Общие вопросы Javascript 9 13.02.2016 00:17
Контекст функции при вызове по таймеру Bombus Общие вопросы Javascript 14 14.11.2013 08:37
proxy() и изменение переданного в контекст объекта lamo4ok jQuery 1 15.05.2013 16:52
не понимаю как задать правильный контекст loz Dojo toolkit 2 17.02.2011 18:36
[jQuery] [Обработка клика] Как не потерять текущий контекст внутри обработчика? xintrea Events/DOM/Window 1 10.02.2011 16:34