【问题标题】:Javascript function running multiple times in Firefox only once in Chrome, why?Javascript 函数在 Firefox 中运行多次,在 Chrome 中只运行一次,为什么?
【发布时间】:2013-05-08 16:51:25
【问题描述】:

我有一个文件上传字段,我添加了一个 jQuery 更改。

在 chrome 中效果很好,loadImage 函数用要上传的图片的渲染替换占位符图片。在 Firefox 中,以下代码呈现 3 次(控制台中有 3 个“1”,但 onchange 处理程序中只有一个“2”),然后在添加图像后将其删除。

为什么在 Firefox 中会发生这种情况,我该如何预防?

Coffeescript(如果有人更喜欢阅读 js,我可以转换):

$('#project_display_pic').change (e) ->
  console.log "2"
  value = $(this).val()
  value = value.replace("C:\\fakepath\\","")
  $('#display_pic_uploader > p').text(value)
  loadImage(
    e.target.files[0],
    ( (img) -> 
      console.log "1"
      $('#display_pic_preview > img').remove()
      $('#display_pic_preview').append(img)
    ),
    {maxWidth: 212}
  )

Haml 如果有帮助(#project_display_pic 是文件字段的 id):

    #display_pic_preview
      = image_tag( @project.display_pic.medium.url, :class => "default_pic" )
    #display_pic_uploader
      %p Add display image
      = f.file_field :display_pic

【问题讨论】:

  • 我正在使用this plugin 显示所选图像的图像预览。 loadImage() 函数接受 File 或 Blob 对象或简单的图像 URL(例如“example.org/image.png")作为第一个参数。如果将 File 或 Blob 作为参数传递,如果浏览器支持 URL API,它会返回 HTML img 元素或 FileReader 对象(如果支持),或者为 false。

标签: javascript jquery ruby-on-rails coffeescript


【解决方案1】:

查看the plugin's code,它似乎为图像对象的onloadonerror 事件调用了您的渲染回调。也许 Firefox 错误地将图像的缩放视为加载事件或其他什么?或者错误事件可能无缘无故被触发。

无论如何,快速修复可能是这样的:

# Builds a function to show the loaded image
# The function stores the last img object it received,
# and doesn't try to show the same one twice in a row
createRenderCallback = ->
  lastImg = null

  (img) ->
    return if img is lastImg # don't handle the same img twice
    # Note that if the image failed to load, `img` will be undefined
    # You may want to check for that before trying to append it
    $('#display_pic_preview > img').remove()
    $('#display_pic_preview').append(img)
    lastImg = img # remember the img

# Attach the file input's change handler (pretty much the same as before)
$('#project_display_pic').change (e) ->
  value = $(this).val().replace("C:\\fakepath\\","")
  $('#display_pic_uploader > p').text(value)
  loadImage e.target.files[0], createRenderCallback(), { maxWidth: 212 }

您可以在插件的代码中做类似的事情,以避免它重新调用回调。或者您可以从插件中记录一些内容以准确查看发生了什么。


编辑:由于将图片插入 DOM 似乎会触发渲染回调,你可以试试这个:

createRenderCallback = ->
  lastImg = null

  (img) ->
    return if img is lastImg
    lastImg = img # <-- Move this line to here, i.e. before inserting the image
    $('#display_pic_preview > img').remove()
    $('#display_pic_preview').append(img)

或者,您可以简单地删除事件侦听器,而不是保留lastImg的记录

renderCallback = ->
  if img? # this function was called from an onload event
    img.onload = img.onerror = null

  else  # called from an onerror event
    @onload = @onerror = null

  $('#display_pic_preview > img').remove()
  $('#display_pic_preview').append(img) if img?

$('#project_display_pic').change (e) ->
  value = $(this).val().replace("C:\\fakepath\\","")
  $('#display_pic_uploader > p').text(value)
  loadImage e.target.files[0], renderCallback, { maxWidth: 212 }

【讨论】:

  • 哇,谢谢,堆栈溢出太不可思议了,您为此投入的时间超出了我的要求。
  • 我尝试了自定义回调,仍然是同样的故事,我认为你对错误是正确的,错误时它会触发回调,有趣的是,当我注释掉这两行 $('#display_pic_preview > img ').remove() $('#display_pic_preview').append(img) 我没有得到回调 x 3,请深入研究。
  • @AlexMarchant 有趣 - 我实际上认为可能是这种情况(插入图像会触发回调),但因为这看起来很荒谬而被驳回。您可以尝试 2 件事 - 我已经更新了答案
【解决方案2】:

firefox 多次调用此函数时出错。此代码也应该可以工作(通过检查宽度属性检查它是否是图像对象:

loadImage(file, function(image) {
        if(typeof(image.width) !== "number") { // make sure its an image and not an error
          return;
        }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 1970-01-01
    • 2022-12-16
    • 2015-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多