Übergeben Sie die Javascript-Funktion als data-*-Attribut und führen Sie sie aus

Lesezeit: 6 Minuten

Wir kennen solche Syntaxen wie unten, wenn wir a definieren value zum onClick Attribut:

<button type="submit" onclick="alert('hi');"></button>
<button type="submit" onclick="doWork"></button> <!-- This one doesn't work -->
<button type="submit" onclick="doWork()"></button>
<button type="submit" onclick="doWork('Mike', 2)"></button>

Was mich interessiert, ist, einen Brauch zu definieren data-attribute und führen Sie den Wert wie folgt aus:

<button type="submit" data-callback="alert('hi');"      class="marker"></button>
<button type="submit" data-callback="doWork"            class="marker"></button>
<button type="submit" data-callback="doWork()"          class="marker"></button>
<button type="submit" data-callback="doWork('Mike', 2)" class="marker"></button>

<script type="text/javascript">
    jQuery("body").on("click","button.marker", function(e) {
        var callback = jQuery(e.currentTarget).data("callback");

        // Now I need to execute the callback no matter of the format
        // 1. Execute as function's body
        // 2. Or by function 'name'
        // 3. Or by function 'name' with 0 parameters
        // 4. Or by function 'name' with n parameters
    })

    function doWork(name, nr){
        var personName = name || "Unnamed";
        var personNr = nr || 0;
        alert("Name is: " + personName + " Nr: " + personNr);
    }
</script>

Ich habe das Beispiel eingefügt jsBin

Wie kann dasselbe Verhalten mit benutzerdefinierten Datenattributen erreicht werden?

  • Sie können sich den Teufel ansehen bewerten()

    – Arun P. Johny

    4. Mai 2015 um 10:55 Uhr


  • Gibt es einen Grund, warum Sie die dynamische Bindung vermeiden? Würde das Thema vereinfachen.

    – Taplar

    4. Mai 2015 um 11:01 Uhr

  • Wenn Sie keinen wirklich guten Grund haben / nur experimentieren, scheint das Schreiben von Code in ein Datenattribut nur eine schlechte Idee zu sein! Sie können den Rückruf einfach auf die Schaltflächen setzen $(.marker).myCallback = doWork; Fühlen Sie sich frei, meine Meinung zu erweitern, wenn Sie nicht einverstanden sind 🙂

    – Michiel Cornille

    4. Mai 2015 um 11:05 Uhr


  • @ Taplar Ja. Das Beispiel ist vereinfacht. Im Produktionscode soll der Callback von anderen Komponenten und zu einem späteren Zeitpunkt aufgerufen werden.

    – Christian E.

    4. Mai 2015 um 11:05 Uhr

  • @Mvision: AngularJS hält das Schreiben von Code in Attributen nicht für eine schlechte Idee 🙂 Es ist sein Kern und meiner Meinung nach sogar das, was es ausmacht Weg besser zu verwenden als jQuery.

    – Jeremy Thille

    4. Mai 2015 um 11:08 Uhr

Benutzer-Avatar
Arun P. Johny

Eine Möglichkeit ist die Verwendung bewerten()

jQuery(".container").on("click", "button.marker", function (e) {
    var callback = jQuery(e.currentTarget).data("callback");

    var x = eval(callback)
    if (typeof x == 'function') {
        x()
    }
});

Demo: Geige

Hinweis: Stellen Sie sicher, dass es in Ihrer Umgebung sicher ist, dh es besteht keine Möglichkeit der Skriptinjektion aufgrund schlechter Eingaben von Benutzern

  • Ich glaube eval("doWork('Mike', 2)") startet die Funktion selbst. Sie müssen es nicht neu starten, indem Sie weitere hinzufügen ().

    – Jeremy Thille

    4. Mai 2015 um 11:03 Uhr

  • @JeremyThille das ist der data-callback="doWork" Fall, in dem eine Funktionsreferenz übergeben wird

    – Arun P. Johny

    4. Mai 2015 um 11:03 Uhr

  • Ich stimme zu, aber ich denke, OP sucht nach der einen oder anderen Lösung, und sie werden sich für eine der beiden entscheiden "dowork" oder "dowork()" Syntax, machen die if (typeof x == 'function') Test nutzlos.

    – Jeremy Thille

    4. Mai 2015 um 11:05 Uhr

  • @JeremyThille Ich habe das deswegen gemacht Or by function 'name' – Ich bin davon ausgegangen, dass OP gemeint ist, dass eine Funktionsreferenz (Name) übergeben wird, die ausgeführt werden muss

    – Arun P. Johny

    4. Mai 2015 um 11:07 Uhr

  • @ArunPJohny Auch wenn JeremyThille mit der Antwort schneller war. Ich werde Ihre als akzeptiert markieren, daher ist sie für zukünftige SO-Benutzer “vollständiger”. Vielen Dank

    – Christian E.

    4. Mai 2015 um 11:55 Uhr

Benutzer-Avatar
Taplar

Ich denke, eine bessere Idee wäre, die Ereignisse dynamisch zu binden und sie auszulösen. Wenn Sie möchten, dass sie nur durch anderen Code bekannt sind, können Sie benutzerdefinierte Ereignisse verwenden.

<button type="submit" class="marker marker1"></button>
<button type="submit" class="marker marker2"></button>
<button type="submit" class="marker marker3"></button>
<button type="submit" class="marker marker4"></button>

<script>
    var $markers = $('.marker');
    $markers.filter('.marker1').bind('customCallback', function(){ alert("hi"); });
    $markers.filter('.marker2').bind('customCallback', function(){ doWork(); });
</script>

Dann könnten Ihre anderen Komponenten sie mit $(selector).trigger(‘customCallback’); aufrufen.

  • müsste das nicht .filter(‘.marker1’) mit einem Punkt sein? 🙂

    – Michiel Cornille

    4. Mai 2015 um 11:14 Uhr

Benutzer-Avatar
Jeremy Thille

Einfach mit:

 $("body").on("click","button.marker", function(e) {
     eval($(this).data("callback"));
 })

  • Wie übergebe ich Parameter?

    – Tim Kretschmer

    8. März 2017 um 5:52 Uhr

  • Die Parameter sind in der Funktion, aber alles ist fest codiert: data-callback="doWork('Mike', 2)"

    – Jeremy Thille

    8. März 2017 um 9:39 Uhr

  • ja, deshalb war meine frage, wie man durchkommt. Natürlich weiß ich, dass wir hart codieren können. eval("function")(args) wird nicht funktionieren

    – Tim Kretschmer

    9. März 2017 um 4:09 Uhr

  • Nun, ich denke, wenn die doWork Funktion ist global, Sie können so etwas tun window[ $(this).data("callback") ](arg1, arg2) aber das alles ist sooooo schmutzig :/ Übergeben globaler Funktionen über HTML-Attribute … yurgh … Warum nicht den sauberen Weg gehen und einfach JS-Funktionen in einem isolierten Bereich schreiben?

    – Jeremy Thille

    9. März 2017 um 8:08 Uhr


Benutzer-Avatar
Michiel Cornille

Wenn Sie wirklich Funktionen (mit oder ohne Parameter) von einer Sache zur anderen übergeben wollten, ohne sie als Ereignisse zu binden, könnten Sie dies auf diese Weise tun (ich begann mit der Antwort von @Taplar).

<button type="submit" class="marker marker1"></button>
<button type="submit" class="marker marker2"></button>
<button type="submit" class="marker marker3"></button>
<button type="submit" class="marker marker4"></button>

<script>
  var $markers = $('.marker');
  $markers.filter('.marker1').get(0).customCallback =  doWork;
  $markers.filter('.marker2').get(0).customCallback = function(){ 
    doWork(arg0,arg1); 
  };
</script>

Dann könnten Sie in Ihrer anderen Komponente wie folgt darauf zugreifen:

<script>
  $('.marker').each(function(){
    var  thisFunction = $(this).get(0).customCallback;
    //do something useful with thisFunction
  });
</script>

Sie können eine Funktion einfach als Datenattribut binden

const ele = $('button');

ele.data('onClick', evt => {
    alert('bye');
})

ele.click(evt => {
    const ele = $(evt.target);
    ele.data('onClick')(evt);
})

  • Es ist erwähnenswert, dass dies nicht als Datenattribut im DOM gespeichert wird. JQuery abstrahiert das und verwaltet diese Daten in sich selbst. In Attributen können nur Zeichenfolgen gespeichert werden. Das heißt, es kann nicht in nativem JS gelesen werden. Immer noch eine viel bessere Lösung als die Verwendung von eval, vorausgesetzt, jQuery ist verfügbar.

    – ste2425

    17. September 2018 um 10:57 Uhr


Benutzer-Avatar
Asuka165

Ein anderer Weg ist die Verwendung window[func](args).

Ähnlich wie eval()aber Sie müssen den Funktionsnamen und das Argument separat im HTML-Attribut speichern.

Hier ist ein kurzes Beispiel …
CodePen

<button type="submit" data-func="Angel" data-args="use me instead of evil()" class="marker">TEST</button>

<script type="text/javascript">

    //=== The Listener =====
    $(".marker").on("click",function(){

        // Get the function name and arguments
        let func = $(this).attr("data-func");
        let args = $(this).attr("data-args");

        // Call the function
        window[func](args);
    })


    //=== The Function =====
    function Angel(msg){
        alert(arguments.callee.name + " said : " + msg);
    }
</script>

  • Es ist erwähnenswert, dass dies nicht als Datenattribut im DOM gespeichert wird. JQuery abstrahiert das und verwaltet diese Daten in sich selbst. In Attributen können nur Zeichenfolgen gespeichert werden. Das heißt, es kann nicht in nativem JS gelesen werden. Immer noch eine viel bessere Lösung als die Verwendung von eval, vorausgesetzt, jQuery ist verfügbar.

    – ste2425

    17. September 2018 um 10:57 Uhr


1206520cookie-checkÜbergeben Sie die Javascript-Funktion als data-*-Attribut und führen Sie sie aus

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy