Git Product home page Git Product logo

Comments (15)

printercu avatar printercu commented on August 15, 2024 1

@nicklozon can you please give a try for https://gist.github.com/printercu/e202851c370ffc38bcdedeb8300d417e It should work fine both for .vue files and <script type='x-template'>. I don't use div templates because they have some limitations/edgecases and can show template source on page while page load, so have not tested for them.

Compiled coffee => js
// Inspired by
// https://github.com/jeffreyguenther/vue-turbolinks/blob/master/index.js
// but changed to support going back to cached page with vue instance.
// Original version will keep instance created from cache along with new one.
var plugin;

plugin = {
  instances: [],
  bind: function() {
    // Destroy instances on current page when moving to another.
    document.addEventListener('turbolinks:before-cache', function() {
      return plugin.cleanupInstances();
    });
    // Destroy left instances when previous page has disabled caching.
    document.addEventListener('turbolinks:before-render', function() {
      return plugin.cleanupInstances();
    });
    // Clear instances on curent page which are not present anymore.
    return document.addEventListener('turbolinks:load', function() {
      return plugin.cleanupInstances(function(x) {
        return document.contains(x.$el);
      });
    });
  },
  cleanupInstances: function(keep_if) {
    var i, instance, len, ref, result;
    result = [];
    ref = plugin.instances;
    for (i = 0, len = ref.length; i < len; i++) {
      instance = ref[i];
      if (typeof keep_if === "function" ? keep_if(instance) : void 0) {
        result.push(instance);
      } else {
        instance.$destroy();
      }
    }
    return plugin.instances = result;
  },
  Mixin: {
    beforeMount: function() {
      // If this is the root component,
      // we want to cache the original element contents to replace later.
      // We don't care about sub-instances, just the root
      if (this === this.$root) {
        plugin.instances.push(this);
        return this.$originalEl = this.$el.outerHTML;
      }
    },
    destroyed: function() {
      if (this === this.$root) {
        // We only need to revert the html for the root component.
        return this.$el.outerHTML = this.$originalEl;
      }
    }
  },
  install: function(Vue, _options) {
    plugin.bind();
    return Vue.mixin(plugin.Mixin);
  }
};


// export default plugin
// or:
// Vue.TurbolinksAdapter = plugin
// plugin.bind()

from vue-turbolinks.

connorshea avatar connorshea commented on August 15, 2024 1

So I had this problem and it was caused by the same thing as @nicklozon, where I had template code inside my .html.erb file.

<div id="game-library">
  <library
    v-bind:purchased-releases="<%= @purchased_releases.to_json(except: [:created_at, :updated_at]) %>"
  ></library>
</div>

And then in library.js, which I imported into my application.js:

import TurbolinksAdapter from 'vue-turbolinks';
import Vue from 'vue/dist/vue.esm';
import Library from './components/library.vue';

Vue.use(TurbolinksAdapter)

document.addEventListener('turbolinks:load', () => {
  let gameLibrary = document.getElementById("game-library")
  if (gameLibrary != null) {
    const library = new Vue({
      el: '#game-library',
      components: { Library }
    })
  }
});

^^^ the above is what it looks like when the problem exists. ^^^

@printercu's script (this) worked for me, though it does seem like - based on nick's comment previously - you can also avoid this problem by simply not including the Vue.js custom elements in the .html.erb files, e.g. by plugging it into a data- attribute and then mounting it on that, or something?

from vue-turbolinks.

jeffreyguenther avatar jeffreyguenther commented on August 15, 2024

We used to listen for before-cache, you can read about the thinking that lead to the change in #8.

from vue-turbolinks.

printercu avatar printercu commented on August 15, 2024

Ok, but there is issue with disappearing/blinking components on long pageloads/slow internet. You can try any of you existing app with enabled throttling on Network tab in chrome devtools. When you leave page with component, it returns back to initial state for a second or so before new page gets loaded. I've fixed it in my gist from #15: 2 last revisions in https://gist.github.com/printercu/e202851c370ffc38bcdedeb8300d417e/revisions

UPD. blinking is especially noticeable with script-tag templates, as component's initial content is empty.

from vue-turbolinks.

nicklozon avatar nicklozon commented on August 15, 2024

I'm just learning about Vue.js/Rails integration and definitely noticing the flickering in my local development environment when using vue-turbolinks.

I could PR the ability to provide an options parameter for setting your own listener.

Edit: Nevermind. After reviewing a good chunk of Issue discussions on this repo it seems other events have their own issues and turbolinks:visit is the vest, although it does cause some flickering issues.

from vue-turbolinks.

jeffreyguenther avatar jeffreyguenther commented on August 15, 2024

Ya, unfortunately, we haven't found a perfect solution yet. It's tricky to get the two techniques to play nice with each other.

I haven't had the time to do this, but it might be worth investigating if we can issue a change to Turbolinks to allow us to have a better spot in the page's lifecycle to do this work.

from vue-turbolinks.

printercu avatar printercu commented on August 15, 2024

I've re-read again linked issue, and understood that before-cache is not used because it's not fired when cache is disabled. I don't think it's a good solution to make all apps blinking, only because some others may disable cache. I see couple of other solutions:

  • Open issue/pr in turbolinks to make it fire before-cache always (if they have not implemented it yet).
  • Listen for both before-cache & before-visit and use one appropriate depending on page's cache settings.
  • Just make this event configurable, let developers select appropriate one.

from vue-turbolinks.

jeffreyguenther avatar jeffreyguenther commented on August 15, 2024

I'm game to review a PR that handles this complexity for users. I'm interested in an approach that does-the-right-thing:tm: with as little effort from the user as possible, while at the same time as providing an escape hatch if you want to do things on your own. @excid3 what do you think?

from vue-turbolinks.

excid3 avatar excid3 commented on August 15, 2024

The default should be the most compatible event (probably what we currently have), but we can make it so you can override it if you prefer to have it run on another event. I'm fine with making it customizable.

from vue-turbolinks.

nicklozon avatar nicklozon commented on August 15, 2024

I've created a commit (not pushed yet) that allows for an options parameter to be provided so that the event can be overridden. I can push when I get home.

The unfortunate thing is that I still find the page flickers even when using before-cache.

from vue-turbolinks.

excid3 avatar excid3 commented on August 15, 2024

You're probably always going to get a flicker because it has to be unmounted and remounted every time.

The only way you can get by without a flicker is to use the same ID inside your Vue template so that the cache can store the old rendered copy of the Vue app and next pageview it can replace it. You wouldn't need this library to do that.

from vue-turbolinks.

nicklozon avatar nicklozon commented on August 15, 2024

FYI: nicklozon@de9bbe0

Usage would be:

Vue.use(TurbolinksAdapter, { event: 'turbolinks:before-cache' })

from vue-turbolinks.

nicklozon avatar nicklozon commented on August 15, 2024

My "flickering" issue stems from placing my template code directly in my rails erb files. This causes turbolinks to render the template before vue has done it's work.

If I instead use a vue file and the render option on the Vue object, this means I won't see the "flickering", instead I will see an empty page until vue renders the template into the div.

Update: Vue has a v-cloak tag which will actually hide the template until vue is done rendering. Related blog post here.

from vue-turbolinks.

adrianthedev avatar adrianthedev commented on August 15, 2024

this works wonderfully!

I would definitely tweak the repo code to work like this.

Thanks a lot @printercu

from vue-turbolinks.

LostKobrakai avatar LostKobrakai commented on August 15, 2024

How about just this? Use whatever comes first:

function handleVueDestructionOn(vue) {
  function teardown() {
    vue.$destroy();
    document.removeEventListener('turbolinks:before-cache', teardown);
    document.removeEventListener('turbolinks:before-render', teardown);
  }
  document.addEventListener('turbolinks:before-cache', teardown);
  document.addEventListener('turbolinks:before-render', teardown);
}

[]
  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 (this !== this.$root) return
      handleVueDestructionOn(this)
      this.$originalEl = this.$el.outerHTML
    },
[]

from vue-turbolinks.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.