6 Stimmen

jquery Klick-Ereignis nicht ausgelöst, wenn Sie Knockout verwenden

Nach Angaben von Knockout-Klickbindung der Dokumentation "Note 3" verhindert Knockout, dass das Klick-Ereignis die Standardfunktion ausführt. Um dieses Verhalten außer Kraft zu setzen, ist alles, was ich tun muss, true von meiner Handler-Funktion zurückzugeben. Also, ich habe dieses Markup:

<div data-bind="visible:Pages().length == 0">
    <div class="alert alert-info">Click "Parse" button.</div>
    <button class="btn" id="btnParse" title="Parse Tabs">Parse</button>
</div>

Jetzt möchte ich ein Klick-Ereignis an die Schaltfläche wie folgt anhängen:

$(function () {       
    $('#btnParse').on('click', function () { alert('clicked'); return true;});
});

Beachten Sie, dass die Funktion den Wert true zurückgibt. Dieser Even-Handler wird nie ausgelöst. Wie kann ich diese Arbeit zu machen?

9voto

Milimetric Punkte 13196

Der Grund, warum Ihr Click-Handler nie ausgelöst wird, ist, dass er nie auf Ihr Element angewendet wird. Also, wenn Sie dies in Jquery tun:

$('.some-class').on('some-event', someFunction);

Damit der Handler an dieses Ereignis gebunden werden kann, muss jQuery zuerst Ihre $('.some-class') Selektor. In Ihrem Fall ist höchstwahrscheinlich #btnParse noch nicht durch Knockout auf die Seite übertragen, wenn Sie das Ereignis binden. Es ist aber auch möglich, dass das ursprüngliche Element gerendert, zerstört und dann ein anderes Element gerendert wird. In diesem zweiten Szenario würde der Ereignishandler nicht auf der Schaltfläche verbleiben. Eine Alternative (die ich nicht empfehle) besteht darin, den Handler weiter oben im DOM zu binden, z. B. an die document Ebene, und filtern Sie nur die Ereignisse, die etwas mit einer id #btnParse :

$(document).on('click', '#btnParse', function () { console.log('hi'); });

Der Grund, warum ich das nicht empfehle, ist, dass es eine schlechte K.O.-Praxis ist, Sie sollten die click verbindlich, wie in anderen Beiträgen vorgeschlagen. Außerdem verwenden Sie ein id-Attribut, und das ist wirklich keine gute Idee im Allgemeinen für dynamische Inhalte mit Vorlagen - verwenden Sie einfach Klassen, es sei denn, Sie brauchen unbedingt eine id für ein eindeutiges statisches Element.

Was die korrekte Verwendung der Knockout-Klickbindung angeht, so müssen Sie zunächst verstehen, wie Knockout das Scoping durchführt. Wenn Sie zum Beispiel einen Klick innerhalb einer Schleife binden und den Handler von Ihrem Haupt-View-Modell wollen, müssen Sie den übergeordneten Bereich referenzieren, weil die Schleife Ihren Kontext ändert:

<!-- ko foreach: someCollection -->
    <a data-bind="click: $parent.someFunction"></a>
<!-- /ko -->

Wenn Sie außerdem den Javascript-Kontext ändern müssen, mit dem Ihr Handler ausgeführt wird (die this ), dann müssen Sie den Click-Handler wie folgt binden:

<!-- ko foreach: someCollection -->
    <a data-bind="click: $parent.someFunction.bind($parent)"></a>
<!-- /ko -->

Spielen Sie ein wenig damit und stellen Sie eine neue Frage, wenn Sie immer noch verwirrt sind. Viel Glück!

1voto

Flangus Punkte 206

Ich denke, das Problem hat mit der Knockout-Änderung des DOMs zu tun, wo Sie versuchen, das Ereignis zu binden. Um dies zu umgehen, versuchen Sie, die Click-Funktion dem Parent zuzuweisen <div> Element. Wenn Sie den Click-Handler zuweisen, verwenden Sie die Überladung mit einem Selektor, um anzugeben, dass Sie den Klick nur dann behandeln wollen, wenn die enthaltene Schaltfläche angeklickt wird. Ändern Sie zum Beispiel div wie folgt:

<div id="btnContainer" data-bind="visible:Pages().length == 0">
    <div class="alert alert-info">Click "Parse" button.</div>
    <button class="btn" id="btnParse" title="Parse Tabs">Parse</button>
</div>

Und dann ändern Sie Ihr Skript in:

$(function () {       
    $('#btnContainer').on('click', '#btnParse', function () { alert('clicked');});
});

Beachten Sie, dass, wenn diese <div> in einem anderen logischen Block enthalten ist, der das DOM verändert (eine Vorlage, eine foreach-Schleife usw.), müssen Sie wahrscheinlich die #btnContainer Tag auf den ersten Vorfahren des <button> die nicht Teil eines solchen logischen Blocks ist.

0voto

Defigo Punkte 451

In meiner Situation war ich mit einem observableArray arbeiten, die einige jQuery Magie auf jedes Element in diesem Array angewendet müssen. Ich hatte einige Probleme mit der benutzerdefinierten Bindung nicht wollen, zwei varibles von jedem Element in diesem Array zu nehmen. Also, in meiner Verpackung fügte ich einige dieser dunklen mnagic zu einem nicht beobachtbaren Element als eine Funktion, so dass, wenn der Name geklickt wurde, dann die Karte, die ich arbeitete würde an diesem Ort zu bewegen.

HTML:

<ul data-bind="foreach: filteredItems">
    <li class="seat">
        <span class="name" data-bind="text:fullName, click: toggleEmp"></span>
    </li>
</ul>

CODE:

function viewModel() {
    var vm = this;
    vm.empData = function(data) {
        var emp = this;
        emp.office_x_loc = ko.observable(data.xLoc);
        emp.office_y_loc = ko.observable(data.yLoc);
        emp.toggleEmp = function () {
            jQuery('#skyLineMap').lhpMegaImgViewer( 'setPosition', emp.office_x_loc(),emp.office_y_loc(), 0.8, false );
    };//*/
}//*/

Ich hoffe, das hilft

-1voto

Tuan Punkte 5213

Der Hinweis, auf den Sie sich für die Klickbindung beziehen, bezieht sich auf die Methode in Ihrem Viewmodel, nicht auf Ihren benutzerdefinierten Click-Handler.

Mit anderen Worten: Wenn Sie eine data-bind="click: doSomething" im <button> Element, das doSomething() Methode in Ihrem Viewmodel sollte true zurückgeben, wenn Sie möchten, dass sie Ihren benutzerdefinierten Handler ausführt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X