Javascript (Nuxt.js/Vue.js)-脚本只工作一次,在更改路由/刷新页面后停止工作

Javascript (Nuxt.js/Vue.js)-脚本只工作一次,在更改路由/刷新页面后停止工作,javascript,vue.js,vuejs2,vue-component,nuxt.js,Javascript,Vue.js,Vuejs2,Vue Component,Nuxt.js,我正在将我的项目网站“转移”到Vue.js上,上面是Nuxt.js。 我正在将存储在远程服务器中的所有文件的内容复制到本地“静态”文件夹 除了第一次加载页面时运行的JavaScript之外,一切正常,但是如果我通过路由切换到另一个页面,或者刷新当前页面,JavaScript将停止工作 例如,我的项目网站上有这样一个页面: 基本上可以将图像拖动到其他框中,当您将鼠标悬停在包含图像的任何框上时,类会发生变化 我通过CSS复制到本地静态文件夹,工作正常,通过JavaScript复制,它只工作一次,在更

我正在将我的项目网站“转移”到Vue.js上,上面是Nuxt.js。 我正在将存储在远程服务器中的所有文件的内容复制到本地“静态”文件夹

除了第一次加载页面时运行的JavaScript之外,一切正常,但是如果我通过路由切换到另一个页面,或者刷新当前页面,JavaScript将停止工作

例如,我的项目网站上有这样一个页面:

基本上可以将图像拖动到其他框中,当您将鼠标悬停在包含图像的任何框上时,类会发生变化

我通过CSS复制到本地静态文件夹,工作正常,通过JavaScript复制,它只工作一次,在更改路由/刷新页面后停止工作

它的工作原理与您第一次加载页面时的网站一样,但在重新加载/更改路由后,脚本将停止工作,并且在鼠标悬停在框上时没有类更改,等等。。。尽管第一次加载页面时工作正常

昨天在研究这个问题时,相关问题的答案是,这是因为在加载页面时脚本只运行一次,所以当路由发生变化或页面刷新时,脚本不会再次运行

一些人建议添加当页面加载到vue组件中“export default”内的“created()”方法时应该执行的函数

但是,在我的例子中,我没有什么东西是每次加载页面时都要执行的,相反,我只想执行脚本的某一部分,这是只有当用户在页面中通过交互执行某些操作时才会触发的特定函数

没有必要每次都加载脚本,因为交互甚至可能不会发生,这使得脚本和加载时间都变得无用。更不用说如果我将整个脚本添加到“created”方法中,组件会变得一团糟

基本上,我没有找到任何解决这个问题的方法,只有一些会产生副作用的变通方法

以下是我的组件的结构(以下组件来自):


导出默认值{
名称:“拖动”,
负责人:{
链接:[{rel:'stylesheet',type:'text/css',href:'css/drag.css'}],
脚本:[{src:'js/drag.js'}]
}
}
有解决这个问题的技巧吗?还是我的处境的变通办法


PS-每次我关闭选项卡并打开一个新选项卡时,脚本都会再次工作,直到页面刷新/路由更改为止

您可以用vue组件样式重写代码。这将更加清楚。并且易于重复使用

 <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>

导出默认值{
名称:“拖动”,
道具:{
范围:{
类型:数字,
默认值:5
}
},
数据(){
返回{
已拖动:“”
}
},
方法:{
排水剂:功能(e){
e、 target.className+=“悬停”
},
德拉戈弗:功能(e){
e、 预防默认值()
},
dragLeave:函数(e){
e、 target.className='box'
},
dragDrop:函数(e){
e、 target.className='box'
e、 target.appendChild(this.drauged)
},
dragStart:函数(e){
e、 target.className+='ondrag'
this.draw=e.target
setTimeout(()=>(e.target.className='invisible'),0)
},
绘图:功能(e){
e、 target.className='fill'
}
}
}
.拖{
背景色:黑色;
显示器:flex;
调整内容:灵活启动;
}
.盒子{
背景色:白色;
宽度:160px;
高度:160px;
盒影:0.10px rgba(0,0,0,0.5);
右边距:15px;
边框:3倍白色固体;
}
.填充{
背景图像:url('http://source.unsplash.com/random/150x150');
宽度:150px;
高度:150像素;
保证金:5px 5px;
光标:指针;
}
昂德拉格先生{
边框:实心#ccc 4px;
}
.无形的{
显示:无;
}
.盘旋{
背景#f4;
边框样式:虚线;
}

这是一个丑陋的、完全不好的主意,但正是你所要求的。使用nuxt,您可以使用旧的link元素而不是router link或nuxt link绕过导航问题,从而强制刷新整个页面

记住nuxt在通用模式下,服务器呈现第一个页面,其余的导航是实时重新加载为SPA,您的问题与addEventListener关联,因为在第一次访问中,您添加了这个,但从未删除它们

因此,使用link元素进行导航时,您强制刷新整个页面,每次都是第一次访问。之后,为了确保元素在应用之前存在,您可以在模板底部添加脚本,页面将为:

<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>

导出默认值{
名称:“拖动”,
负责人:{
链接:[{rel:'stylesheet',键入:'text/css',href:'css/drag.css'}]
}
}

我添加了一个指向/用于测试的链接

在您的示例中,一切都按照预期工作-不确定您的情况是什么?是否要在组件之外使用脚本?刷新页面后,或者当我转到主页并返回到当前页面时,脚本停止工作,就好像它根本没有链接一样,尽管它在第一次将页面加载到当前选项卡时起作用,但这是解决问题的唯一方法吗?我真的不想这样做,因为对所有的页面都这样做需要一段时间。。。根据脚本,组件中可能有太多的函数。还有,有没有一种方法可以在外部JavaScript文件中设置方法,并在组件中使用它们,而不必从组件中导入函数?例如,在元素的div中设置vue方法,使用外部JavaScript文件中定义的相同函数名,并随页面一起加载,这也感谢您花时间进行此设置
<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>