jeffreyguenther / vue-turbolinks

A Vue mixin to fix Turbolinks caching
MIT License
287 stars 20 forks source link

Component is kept on cached page until next visit #15

Closed printercu closed 6 years ago

printercu commented 6 years ago

Hi, and thanks for the plugin!

I've found that there can be 2 similar components on page when returning back to page which was previously cached:

When component is created with inline js in page, it runs twice on second visit: when page is shown from cache and then for fresh one. This is not a problem in most cases, but my component was polling some api (it's stopped in beforeDestroy), so I noticed that all requests are doubled.

I've slightly changed original plugin to handle such cases. It's made with coffeescript and uses jquery - i'm not familiar with modern js. However, i hope this may help:

components = []

# Destroy components on current page when moving to another.
$(document).on 'turbolinks:visit', ->
  component.$destroy() for component in components

# Clear components on curent page which are not present anymore.
$(document).on 'turbolinks:load', ->
  for component in components
    component.$destroy() unless $.contains(document, component.$el)

Vue.TurbolinksAdapter =
  beforeMount: ->
    # If this is the root component,
    # we want to cache the original element contents to replace later.
    # We don't care about sub-components, just the root
    if @ == @$root
      components.push(@)
      @$originalEl = @$el.outerHTML

  destroyed: ->
    # We only need to revert the html for the root component.
    @$el.outerHTML = @$originalEl if @ == @$root
excid3 commented 6 years ago

Could you provide a simple example that shows what happens?

printercu commented 6 years ago

https://github.com/printercu/vue_turbolinks_example

bin/setup should be enough. Steps to reproduce:

I've put example into separate commit: https://github.com/printercu/vue_turbolinks_example/commit/17cbcbd6b1bf320f63958a5db63749a34453e3ff

printercu commented 6 years ago

Hi! Any update on it? Did sample app help? I've found an issue in my original mixin that it didn't clean up old instances. Here is updated one, which can be used either as plugin or as mixin: https://gist.github.com/printercu/e202851c370ffc38bcdedeb8300d417e

excid3 commented 6 years ago

Your setup and teardown is overly complicated here. One of the primary things is that if you're going to use Turbolinks, you should always run your Javascript on the turbolinks:load event, not when the DOM is ready / DOMContentLoaded otherwise you can end up running your Javascript multiple times.

The library currently works with multiple Vue apps on the same page. Take a look at this example instead:

https://github.com/excid3/multiple-vue-apps/blob/master/app/javascript/packs/application.js

printercu commented 6 years ago

Ok, I'm not going to persist on this changes to be included. Turbolinks official docs says that it's better to use turbolinks:load event for such things:

Turbolinks evaluates Githubissues.

  • Githubissues is a development platform for aggregating issues.