У меня есть событие data-bind="click: ..." в Knockout.js, и я пытаюсь отключить его, когда в элементе присутствует класс disabled.

<span class="disabled" data-bind="click: alerting">Two</span>

Я пытаюсь это без успеха

$('.disabled').click(function(e){
    e.preventDefault();
});

Воспроизведение онлайн

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

1
Alvaro 17 Дек 2015 в 18:28

5 ответов

Лучший ответ

Проблема здесь в том, что нет никакой гарантии относительно того, какой обработчик кликов будет запущен первым. В этом случае привязка клика по выбыванию выполняется перед обработчиком jquery.

Учитывая, что вы работаете с нокаутом, «правильный» способ сделать так, чтобы viewmodel обрабатывал все, а не полагался на что-то внешнее, такое как jQuery, чтобы предотвратить щелчок.

В вашем случае viewmodel может выглядеть так:

var viewModel = {
    disabled: ko.observable(false),
    alerting: function(data, e) {
       if (!this.disabled())
           alert("two");
    }
};

Затем вы просто обновляете наблюдаемую disabled, чтобы включить / отключить обработчик кликов. Вы также можете использовать это наблюдаемое для применения различных стилей к элементам, которые должны быть отключены, например, добавление отключенного стиля вместо использования стиля для управления поведением выбивания.

2
James Thorpe 17 Дек 2015 в 15:38

Вы должны использовать disabled attr, чтобы отключить элемент. Вы можете иметь дело с визуальным стилем, используя это:

a:disabled {
    color: red;
}

Вы также можете проверить класс отключения внутри функции нокаута (не рекомендуется, просто пример). Вот так http://jsfiddle.net/mCxjz/81/

0
Fabio Luz 17 Дек 2015 в 15:46

Я обновил ваш код в соответствии с вашими требованиями. Что я понимаю из jQuery, так это то, что выполнение .click только привязывает больше событий к элементу. Следующий код переопределяет существующий обработчик кликов.

$._data($(elem)[0], 'events').click[0].handler = function() {return;}

Если вы хотите вернуть свою старую функцию, возможно, сохраните ее в var и переназначьте позже. Надеюсь это поможет.

http://jsfiddle.net/mCxjz/84/

-2
jkris 17 Дек 2015 в 15:47

Есть несколько способов, которые я мог бы придумать, чтобы вы справились с этим требованием.

В этом рабочем примере я поместил несколько вариантов, чтобы вы могли их посмотреть: http: // plnkr. сотрудничество / редактировать / t1jG3JmsywxteRyNNKS4 ? р = предварительный просмотр.

Я также разбудил ваш JSFiddle здесь http://jsfiddle.net/8pa84cmu/1/

<p>Option 1 - Applying the disabled class, leave button clickable but check for class in click handler and do nothing</p>
<button class="disabled" data-bind="click: RegisterClick">Click</button>
<hr/>
<p>Option 2 - An enabled button doing what the click handler asks</p>
<button class="enabled" data-bind="click: RegisterClick">Click</button>
<hr/>
<p>Option 3 - A binding using a boolean to apply the class name if required and disabling it if required</p>
<button data-bind="click: RegisterClick, css: { disabled }, disable: disabled">Click</button>
<hr/>
<p>Option 4 - A binding just dealing with enabling / disabling</p>
<button data-bind="click: RegisterClick, enable: IsEnabled">Click</button>
var ViewModel = function() {
  this.RegisterClick = function(model, event) {
    if (event.target.className === "disabled") {
      return;
    }

    console.log("Clicked");
  }

  this.disabled = true;
  this.IsEnabled = false;
}

window.onload = function() {
  ko.applyBindings(new ViewModel());
}
1
James Thorpe 17 Дек 2015 в 16:02

Вот как вы можете управлять стилем элемента, и чтобы обратный вызов учитывал этот стиль. Если бы у вас было 20 элементов, которые вы хотели бы совместить, вы бы использовали одну и ту же наблюдаемую для каждого из них. Этот пример создает три кликабельных участка и отключает их через 2,5 секунды. Вы можете увидеть изменение стиля.

var viewModel = {
  isDisabled: ko.observable(false),
  alerting: function(data, event) {
    if ($(event.target).hasClass('disabled')) return;
    alert(event.target.innerHTML);
  }
};

ko.applyBindings(viewModel);

setTimeout(function () {
	viewModel.isDisabled(true);
}, 2500);
.clickable {
  border-radius: 5px;
  padding: 5px;
  background-color: lightgreen;
  cursor: pointer;
}
.disabled {
  background-color: lightgray;
  cursor: not-allowed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<span class="clickable" data-bind="click: alerting, disabled: isDisabled, css: {disabled: isDisabled}">One</span>
<span class="clickable" data-bind="click: alerting, disabled: isDisabled, css: {disabled: isDisabled}">Two</span>
<span class="clickable" data-bind="click: alerting, disabled: isDisabled, css: {disabled: isDisabled}">Three</span>
0
Roy J 17 Дек 2015 в 16:20