首页 > 解决方案 > 使用 NuxtLink 重新运行外部 JavaScript

问题描述

我正在为我的 Nuxt 应用程序的客户端/前端设计使用多个外部 JavaScript 文件(Nuxt 通用模式,服务器端渲染 + 客户端导航),将它们放在 nuxt.config.js 文件中。

nuxt.config.js

<script>
export default {
  head () {
    return {
      script: [
        { src: '/scripts/jquery.min.js', body: true },
        { src: '/scripts/jquery.dropotron.min.js', body: true },
        { src: '/scripts/browser.min.js', body: true },
        { src: '/scripts/breakpoints.min.js', body: true },
        { src: '/scripts/util.js', body: true },
        { src: '/scripts/main.js', body: true },
        { src: '/scripts/owa.js', body: true }
      ]
    }
  }
}
</script>

在初始页面浏览中一切都运行良好,但不幸的是,当使用NuxtLink导航到另一个页面时,EventListeners 消失了。我由此得出结论,虚拟 DOM 被重新渲染,但一旦完成,JavaScript 函数就不会再次运行。

当然,我可以使用 a-Tags 而不是 NuxtLink,这样整个站点将再次加载,脚本也会如此,但这是不好的做法,与 SPA 无关。

我已经尝试过 Nuxt 中间件,但删除 Head 中的脚本(见示例代码)不起作用。

middleware/rerunJs.js

  const scripts = context.app.head.script
  context.app.head.script = undefined
  context.app.head.script = scripts

任何想法将不胜感激!

更新

客户端控制台输出 - 初始页面加载

Logging: rerunJs.js in middleware directory
Server based middleware
Print context.app.head.script:
[
  { src: '/scripts/jquery.min.js', body: true, defer: true },
  { src: '/scripts/jquery.dropotron.min.js', body: true, defer: true },
  { src: '/scripts/browser.min.js', body: true, defer: true },
  { src: '/scripts/breakpoints.min.js', body: true, defer: true },
  { src: '/scripts/util.js', body: true, defer: true },
  { src: '/scripts/main.js', body: true, defer: true },
  { src: '/scripts/owa.js', body: true }
]
Logging: index.vue in Nuxt pages directory
Logging: jquery.dropotron.min.js in static/scripts directory
Logging: main.js in static/scripts directory

客户端控制台输出 - 使用 NuxtLink 导航到路由“/”

Logging: rerunJs.js in middleware directory
Client based middleware
Print context.app.head.script:
Array(7) [ {…}, {…}, {…}, {…}, {…}, {…}, {…} ]

标签: javascriptdomnuxt.jssingle-page-applicationpageload

解决方案


解决方案

当使用 NuxtLink 将 Nuxt 设置为通用模式时,要重新运行外部 JavaScript(即 jQuery),需要使用两个生命周期挂钩。

首先,中间件应该从头中删除脚本。请确保,只有客户端会删除脚本。在初始页面加载时,中间件是基于服务器的并且脚本运行,即使没有触发它们。

middleware/rerunJs.js

...
  if (process.client) {
    context.app.head.script = undefined
  }
...

之后,所需页面的mounted-Hook 应将脚本附加到正文的开头和结尾。

pages/index.vue

...
  mounted () {
    (function LoadMyJs () {
      const docHeadObj = document.getElementsByTagName('head')[0]
      const jqueryScript = document.createElement('script')
      jqueryScript.outerHTML = '<scr' + 'ipt data-n-head="ssr" src="/scripts/jquery.min.js" data-body="true">' + ' </scr' + 'ipt>'
      jqueryScript.src = '/scripts/jquery.min.js'
      jqueryScript.defer = true

      docHeadObj.appendChild(jqueryScript)

      document.body.innerHTML = document.body.innerHTML + queryScript.outerHTML 
    }())
  }
...

推荐阅读