尝试在Fancybox回调内调用CoffeeScript方法时出现范围问题



我有以下名为Course的CoffeeScript模块。我有一小段代码想重复使用,我创建了一个名为preSelectItemSize的方法。

我想在调用init时以及在afterShow Fancybox回调中调用此方法。下面的代码工作,但它认为使用模块名称是不正确的,我应该使用@引用来代替"this"。

我做错了什么?(为简洁起见,减少了代码片段)

$ = window.jQuery = require("jquery")
Course =
  init: ->
    $('.js-product-overlay').on 'click', (e) =>
      @viewProductClickHandler(e, MediaDetection)
    @preSelectItemSize()
  viewProductClickHandler: (e, mediaDetection) =>
    $('.js-product-overlay').fancybox({
      href: wishlist_overlay_href
      maxWidth: '775px'
      minHeight: '495px'
      autoCenter: '!isTouch'
      height: 'auto'
      scrolling: true
      fitToView: false
      autoSize: false
      padding: 0
      tpl:
        closeBtn: '<a class="fancybox-item modal__close fancybox-close" href="javascript:;">Close</a>'
      afterShow: ->
        $('.js-fancybox-close').on 'click', (e) ->
          e.preventDefault()
          $.fancybox.close()
        Course.preSelectItemSize()
    })
  preSelectItemSize: ->
    itemId = $('.modal__product-info').attr('data-item-id')
    $('#size-' + itemId).click()
module.exports = Course

我认为您真正的问题是,您使用的是一个简单的对象文字,而不是一个类,因此=>的行为并不像您期望的那样,您只能按名称引用Course

如果我们看一个简化的例子:

o =
  m: =>

我们可以通过查看生成的JavaScript来了解发生了什么:

var o;
o = {
  m: (function(_this) {
    return function() {};
  })(this)
};

因为我们只有一个简单的数据结构(即一个普通的旧对象文字),所以没有构造函数将m绑定到任何实例,它的行为就像你说的那样:

m = =>
o = m: m

所以o(或者在您的例子中是Course)的任何函数属性都只是简单的旧属性,碰巧是函数,它们并不是真正的方法。

您可以去掉所有的胖箭头并按名称引用Course,也可以切换到一个类,这样CoffeeScript就有一个实例可以将东西绑定到:

class Course
  #...
module.exports = new Course

通过将viewProductClickHandler更改为细箭头并将afterShow回调更改为胖箭头,可以实现以下操作:

Course =
  init: ->
    $('.js-product-overlay').on 'click', (e) =>
      @viewProductClickHandler(e, MediaDetection)
    @preSelectItemSize()
  viewProductClickHandler: (e, mediaDetection) ->
    $('.js-product-overlay').fancybox({
      href: wishlist_overlay_href
      maxWidth: '775px'
      minHeight: '495px'
      autoCenter: '!isTouch'
      height: 'auto'
      scrolling: true
      fitToView: false
      autoSize: false
      padding: 0
      tpl:
        closeBtn: '<a class="fancybox-item modal__close fancybox-close" href="javascript:;">Close</a>'
      afterShow: =>
        $('.js-fancybox-close').on 'click', (e) ->
          e.preventDefault()
          $.fancybox.close()
        @preSelectItemSize()
    })
  preSelectItemSize: ->
    alert "preSelectItemSize executed."
    itemId = $('.modal__product-info').attr('data-item-id')
    $("#size-#{itemId}").click()
Course.init()

有关工作代码的示例,请参见fiddle:https://jsfiddle.net/L5u31Lzr/1/

最新更新