简体   繁体   中英

(Nuxt.js/Vue.js) - Script only works once, stops working after changing route/refreshing the page

I'm "transferring" my projects website to Vue.js with Nuxt.js on top. I'm copying over the contents of all the files stored in the remote server to the local "static" folder.

Everything is working fine, except the JavaScript that runs for the first time the page is loaded, but if I switch to another page through the routes, or refresh the current page, the JavaScript will stop working.

For instance, there's this page in my projects website: http://archy-user.name/drag/

Where you can basically drag the image to other boxes, with class changes when you hover over any box with the image.

I copied over the CSS to the local static folder, works fine, copied over the JavaScript, it only works once and stops working after changing route/refreshing the page...

It works just like the website when you first load the page, but after reloading/changing route the script just stops working, and there are no class changes when hovering over boxes, etc... Albeit working fine the first time the page is loaded.

Yesterday when researching about this, answers to related questions were saying that this happened because the script is ran only once when the page is loaded, so when there are route changes or the page is refreshed, the script doesn't run again.

Some suggested adding the function supposed to be executed when the page is loaded to the "created()" method inside "export default" in the vue component.

However, in my case, I don't have something that I actually want to execute every time the page is loaded, rather, I want to execute only a certain portion of the script, which would be specific functions triggered only when certain actions are performed by the user in the page through interactions...

Loading the script every time wouldn't be necessary, as the interactions may not even happen, making the script useless, as well as the load time. Not to mention the mess that the component would become if I were to add the whole script to the "created" method.

Basically I didn't find any real fix for this issue, only workarounds that cause side-effects...

Here's how my components are structured (below component is from http://archy-user.name/drag ):

<template>
<div class="container">
    <div class="box">
        <div class="fill" draggable="true"></div>
    </div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
</div>
</template>

<script>
export default {
    name: 'Drag',
    head: {
        link: [ { rel: 'stylesheet', type: 'text/css', href: 'css/drag.css'} ],
        script: [ { src: 'js/drag.js' } ]
    }
}
</script>

<style>

</style>

Any tips to fix this issue? Or workarounds to my situation?

PS - Everytime I close the tab and open a new one, the scripts works again until the page is refreshed/route is changed

You can rewrite your code in vue component style. it will be more clear. and easy to reuse

 <template>
  <div class="drag">
    <div
      v-for="n in range"
      :key="n"
      class="box"
      @dragenter="dragEnter"
      @dragover="dragOver"
      @dragleave="dragLeave"
      @drop="dragDrop"
    >
      <div
        v-if="n === 1"
        class="fill"
        draggable="true"
        @dragstart="dragStart"
        @dragend="dragEnd"
      />
    </div>
  </div>
</template>

<script>
export default {
  name: 'Drag',
  props: {
    range: {
      type: Number,
      default: 5
    }
  },
  data() {
    return {
      dragged: ''
    }
  },
  methods: {
    dragEnter: function(e) {
      e.target.className += ' hovered'
    },

    dragOver: function(e) {
      e.preventDefault()
    },

    dragLeave: function(e) {
      e.target.className = 'box'
    },

    dragDrop: function(e) {
      e.target.className = 'box'
      e.target.appendChild(this.dragged)
    },

    dragStart: function(e) {
      e.target.className += ' ondrag'
      this.dragged = e.target
      setTimeout(() => (e.target.className = 'invisible'), 0)
    },

    dragEnd: function(e) {
      e.target.className = 'fill'
    }
  }
}
</script>

<style>
.drag {
  background-color: darksalmon;
  display: flex;
  justify-content: flex-start;
}

.box {
  background-color: white;
  width: 160px;
  height: 160px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
  margin-right: 15px;
  border: 3px white solid;
}

.fill {
  background-image: url('http://source.unsplash.com/random/150x150');
  width: 150px;
  height: 150px;
  margin: 5px 5px;
  cursor: pointer;
}

.ondrag {
  border: solid #ccc 4px;
}

.invisible {
  display: none;
}

.hovered {
  background: #f4f4f4;
  border-style: dashed;
}
</style>

this is ugly and totally a bad idea but is exact what you ask. using nuxt you can bypass the navigation issue using the old link element instead router-link or nuxt-link, with that you force to refresh the entire page.

remember nuxt in universal mode, server render the first page, the rest of the navigation is live reload as SPA, your issue is realted with addEventListener, because in the first visit you add this but you never remove them.

So using a link element for navigation you force to refresh the entire page, every time will be the first visit. after that to be sure the elements exist before apply you can add the script at the bottom of the template, the page will be:

<template>
  <div>
    <a href="/">
      go Home
    </a>
    <div class="container">
      <div class="box">
        <div
          class="fill"
          draggable="true"
          dragstart="dragStart"
          dragend="dragEnd"
        />
      </div>
      <div class="box" />
      <div class="box" />
      <div class="box" />
      <div class="box" />
      <div class="box" />
    </div>
    <script src="js/drag.js" />
  </div>
</template>

<script>
export default {
  name: 'Drag',
  head: {
    link: [{ rel: 'stylesheet', type: 'text/css', href: 'css/drag.css' }]
  }
}
</script>

I add a link to / for testing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM