jQuery: onClick Undefined?

2019-03-06 23:03发布

I'm having issues with onclick, specifically the onclick="Foo()" seen in the code below. When clicked, I'm getting undefined, yet I have included the function at the top and even out of the function.

$( document ).ready(function() {
    function Foo() {
        console.log('clicky click click');
        document.getElementById('categoryBubble').style.display = 'none';
    }
    $('.mutliSelect select').on('change', function() {
        var title = $(this).closest('.mutliSelect').find('option').val();
        title = $(this).val() + "";
        if ($(this).is(':selected')) {
            // the code for if goes here
        } else {
            console.log('im working here #2');
            var html = '<span id="categoryBubble" title="' + title + '">' + title + '</span>' + '<span onclick="Foo()" class="Xout">x</span>';
            $('.multiSel').append(html);
            $(".hida").hide();
        }
    });
});

2条回答
劳资没心,怎么记你
2楼-- · 2019-03-06 23:16

Foo() (which isn't a constructor function so it shouldn't be named starting with a capital letter) is locally scoped to the anonymous function you pass to ready.

Then the onclick event handler goes looking for something called Foo, it can't find it because it isn't in the right scope.

Don't use intrinsic event attributes, they have all sorts of nasty issues, one of which is that you're pretty much forced to use globals with them.

Generate your HTML with jQuery functions instead of mashing strings together. Bind your event handler with the jQuery on method and not an onclick attribute.

$(function() {
  function foo() {
    console.log("clicky click click");
    document.getElementById("categoryBubble").style.display = "none";
  }

  $(".mutliSelect select").on("change", function() {
    var title = $(this)
      .closest(".mutliSelect")
      .find("option")
      .val();

    title = $(this).val() + "";

    if ($(this).is(":selected")) {
      // the code for if goes here
    } else {
      console.log("im working here #2");

      var span = $("<span />")
        .attr("id", "categoryBubble")
        .attr("title", title)
        .text(title);

      var other_span = $("<span />")
        .on("click", foo)
        .addClass("Xout")
        .text("x");

      $(".multiSel").append(span);
      $(".multiSel").append(other_span);

      $(".hida").hide();
    }
  });
});
查看更多
Explosion°爆炸
3楼-- · 2019-03-06 23:20

Your foo is defined inside the document).ready - it's not on the top level, so when the inline handler tries to find a global function named Foo to call, it fails.

Either put Foo outside:

function Foo() {
  console.log('clicky click click');
  document.getElementById('categoryBubble').style.display = 'none';
}

$( document ).ready(function() {
  // ...

Or, even better, avoid inline handlers entirely, and attach the listener properly using Javascript instead, allowing you to reference other variables and functions inside the current scope:

const span1 = $('<span></span>')
  .prop({
    id: 'categoryBubble',
    title
  })
  .text(title);
const span2 = $('<span></span>')
  .prop('class', 'xOut')
  .on('click', Foo);
$('.multiSel').append(span, span2);

Also note that, in modern versions of jQuery, rather than $( document ).ready(), you can use

$(() => {
  // code here

instead. In addition, having multiple IDs in a single document is invalid HTML; appending

<span id="categoryBubble" 

multiple times (if that's a possibility, given other code you may have) will not be valid. Consider using a class instead.

<span class="categoryBubble"

If you do indeed want to append a span multiple times, and you want clicking on the created span to remove the categoryBubble associated with that span, then the ID selector won't work - instead, you can reference the span created earlier in the closure, and hide it:

const span2 = $('<span></span>')
  .prop('class', 'xOut')
  .on('click', () => {
    span1.hide();
  });
查看更多
登录 后发表回答