Javascript 函数在 Firefox 中运行多次,但在 Chrome 中运行一次,为什么?

标签 javascript jquery ruby-on-rails coffeescript

我有一个文件上传字段,我向其中添加了 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

最佳答案

查看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 }

关于Javascript 函数在 Firefox 中运行多次,但在 Chrome 中运行一次,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9256662/

相关文章:

javascript - React Router V4 使用 Redux-persist 和 React-snapshot 保护私有(private)路由

javascript - div 的 jquery 碰撞检测

ruby-on-rails - 在热切加载关联上指定条件后无法获取对象

javascript - 使用单个 AJAX 请求同时保存多个记录?

javascript - 使用 Jquery 或 Javascript 在 HTML 中获取 div 背景图像的尺寸

javascript - 使用 jquery 在复选框选择上显示/隐藏列

php - 如何使用 CSS 和 Jquery 更改事件链接的颜色

javascript - jQuery:如何查找动态生成 id 的单选按钮是否被选中?

ruby-on-rails - 在 Mavericks 上安装 Rails

javascript - 我正在尝试在文本文件上写入三星 Gear S 的 Tizen 可穿戴应用程序中的一些数据