【问题标题】:Reloading JS scripts on page (transition) change when using Barba JS使用 Barba JS 时在页面上重新加载 JS 脚本(过渡)发生变化
【发布时间】:2021-12-25 22:54:24
【问题描述】:

我正在尝试在 HubSpot 网站上实施 barba.js

考虑以下两页:

  1. 资源
  2. 客户

使用我当前的barba.js 实现,这是我正在经历的当前流程:

  1. 我访问了resources 页面(不是通过转换到它,而是通过/resources 直接访问它)。
  2. 此时,我所有的js 都在工作(slick-sliders、滚动功能等)
  3. 然后我使用导航访问customers 页面。页面已加载,但特定于该页面的模块和表单的所有 js 均无效。

简而言之,js 用于我 transition 不起作用的页面。

为了解决这个问题,我要做的是重新加载 container beforeEnter() 中的所有 scripts

见下文:

$(function() {

  function delay(n){
    n = n || 2000;
    return new Promise((done) => {
      setTimeout(() => {
        done();
      }, n);
    });
  }

  barba.init({
    sync: true,
    prefetchIgnore: true,
    debug: true,
    transitions: [{

      async leave(data){
        const done = this.async();
        await delay(200);
        done();
      },

      async beforeEnter({ next, container }) {

        $(container).find('script').each(function (i, script) {
          var $script = $(script);
          $.ajax({
            url: $script.attr('src'),
            cache: true,
            dataType: 'script',
            success: function () {
              $script.trigger('load');
            }
          });
        });
      },

      async enter(data){
        let scrollX = 0
        let scrollY = 0

        barba.hooks.leave(() => {
          scrollX = barba.history.current.scroll.x;
          scrollY = barba.history.current.scroll.y;
        });

        window.scrollTo(scrollX, scrollY);
      },

      async once(data){
        console.log("done");
      },

    }]
  });

});

但是,我当前的beforeEnter() 仍然产生相同的结果。有什么办法吗?

编辑

为了提供更多详细信息,此barba.js 实现适用于HubSpot 站点。当您在 HubSpot 中创建 custom modules 时,它会在页面上吐出该模块的 JS(在 script 标记中)。例如,下面是 JS 在页面上的渲染方式:

<script>
    // js from custom module is here
</script>

<script src=".../scripts-min.min.js"></script>

因此,当执行 barba 转换时,我需要所有具有 src 的 JS 和内联呈现的那些(如自定义模块)重新加载。

基于User863的反馈的最新方法

$(function() {

  function delay(n){
    n = n || 2000;
    return new Promise((done) => {
      setTimeout(() => {
        done();
      }, n);
    });
  }

  function reload_scripts(param){
    $(param).find('script').each(function (i, script) {
      var $script = $(script);
      $.ajax({
        url: $script.attr('src'),
        cache: true,
        dataType: 'script',
        success: function () {
          $script.trigger('load');
          console.log("scripts loaded");
        }
      });
    });
  }


  barba.init({
    sync: true,
    prefetchIgnore: true,
    debug: true,
    transitions: [{

      async leave(data){
        const done = this.async();
        await delay(200);
        done();
      },

      async beforeEnter(data) {
        reload_scripts(data.next.container);
      },

      async beforeEnter({ next }) {
        reload_scripts(next.container);
      },

      async enter(data){
        // scroll to top of page when transitioning
        let scrollX = 0
        let scrollY = 0

        barba.hooks.leave(() => {
          scrollX = barba.history.current.scroll.x;
          scrollY = barba.history.current.scroll.y;
        });

        window.scrollTo(scrollX, scrollY);
      },

      async once(data){
        console.log("transition complete");
      },

    }]
  });

});

当前行为:与以前相同(页面更改时模块的脚本被破坏)。例如,带有slick slider 的模块不起作用(slick 未启动)。

【问题讨论】:

  • src 的脚本是否正常工作?
  • @User863 - 是的,看起来是这样。我有js 使header 在滚动fixed 上滚动,而这个js 在转换到另一个页面时正在执行。只需要一种方法在没有src的页面上执行js

标签: javascript jquery ajax barbajs


【解决方案1】:

可以通过使用eval 来解决,如下所述:https://github.com/barbajs/barba/issues/32

在cmets上提到的问题:

barba.hooks.after((data) => {
    let js = data.next.container.querySelectorAll('main script');
    if(js != null){
            js.forEach((item) => {
                console.log(js)
                eval(item.innerHTML);
            });
    }
});

【讨论】:

    【解决方案2】:

    根据文档

    beforeEnter 转换的参数将成为对象

    Property Description
    data.current Current page related
    data.next Next page related
    data.trigger Link that triggered the transition

    https://barba.js.org/docs/advanced/hooks/#data-properties

    因此container 属性在data.currentdata.next 属性中都可用。在这种情况下,我们必须使用来自data.next 的与新页面相关的脚本。

    固定代码 #1

    async beforeEnter(data) {
    
        $(data.next.container).find('script').each(function (i, script) {
            // ...
        })
    }
    

    固定代码 #2

    async beforeEnter({ next }) {
    
        $(next.container).find('script').each(function (i, script) {
            // ...
        })
    }
    

    【讨论】:

    • 嗨@User863 - 对上面定义的两种“固定代码”方法有点困惑,你是说AJAX 调用需要在两种方法中都存在吗?我已经更新了我的问题,以根据我从上面的解释来展示我目前的方法
    • @Freddy 当然AJAX 在这两种方法中都需要调用。此外,任何一种方法都足够了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-26
    相关资源
    最近更新 更多