如何在jQuery Mobile应用程序中初始化Vue页面?

时间:2018-10-17 11:58:17

标签: jsp jquery-mobile vuejs2

我正在处理顾问遗留的应用程序。该站点当前基于jQuery,但是这些页面上的某些逻辑确实变得非常复杂,并且相应的javascript有点失控。我想通过重写Vue中的页面来摆脱一些我必须使用jQuery Mobile手动完成的工作。

我不想重写整个网站,只有几页可以帮助我驯服复杂的逻辑并划分代码。我已经处理了各种组件的所有jQuery增强冲突,但是现在我面临jQuery的页面加载机制的问题。

当我导航到用Vue编写的网站时,第一次加载时,一切都会正确初始化并且代码可以正常工作。但是,导航离开并返回该页面后,似乎没有任何效果。看起来Vue根本没有初始化。

我会发布一个示例,但是我只是不知道如何发布一个需要导航以显示问题的示例,所以我能做的最好的事情就是描述复制步骤:

  1. 从使用jQuery Mobile的任何应用程序开始,然后在Vue中重写一个页面。
  2. 导航到Vue页面。页面按预期工作。
  3. 从页面导航回到主要的jQM应用。
  4. 导航回到Vue页面。这次Vue尚未正确初始化。所有HTML元素仍然存在,但是Vue不会与任何东西交互。

1 个答案:

答案 0 :(得分:0)

我设法找到了这个问题的原因,并且由于它在技术上是可行的,因此我将其发布为答案。我知道您不应该将jQuery Mobile和Vue混合使用,并且所有兼容性问题都是主要原因,但是我只是没有从头开始的奢望,我仍然希望获得作为开发人员的好处从框架开始。

这里的问题是jQM的缓存/ SPA架构。我有一个JSP应用程序,正在Vue中重写其单个页面。 vue应用程序的根实例直接写到JSP页面中,因此,当用户加载页面时,它将使用模板获取HTML。例如,假设这是模板:

<html>
  <head>
    <!-- links and scripts -->
    <script src="app.js"></script>
  </head>
  <body>
    <div data-role="page">
      <div data-role="content" class="ui-container">
        <div id="vue-application">
          <input v-model="test_input">
          <p>{{ test_input }}</p>
        </div>
      </div>
    </div>
  </body>
</html>

然后在app.js

$(document).bind("pageinit", function() {
  new Vue({
    el: "#vue-application",
    data: {
      test_input: ""
    }
  });
});

鉴于以上页面,首次加载是可行的,因为模板是从服务器直接加载到DOM中的,然后在div#vue-application初始化Vue时,它将模板从DOM中拉出,对其进行解析,然后初始化它,然后在不使用所有模板语法的情况下将Vue组件重新安装到DOM中。

现在,当您离开页面导航时,jQM将获取div[data-role=page]元素内DOM中的所有内容并将其缓存。此页面的后续导航不会将未更改的模板从服务器中拉出,而是会将其从内存中重新插入到DOM中,但是问题在于Vue已经用正常的DOM元素替换了所有模板代码,并且所有钩子现在都消失了。像pageinit这样的所有事件仍然会触发,并且Vue仍会初始化,但是现在没有要初始化的模板,它只是一个普通的DOM,因此Vue基本上不会挂接到任何东西,而只是初始化了静态HTML页面。 / p>

为了抵消这种缓存,我最终通过Ajax加载div#vue-application的内容,然后初始化应用程序。主页已分为两个文件:

main_page.jsp

<html>
  <head>
    <!-- links and scripts -->
    <script src="app.js"></script>
  </head>
  <body>
    <div data-role="page">
      <div data-role="content" class="ui-container">
        <div id="vue-application"></div>
      </div>
    </div>
  </body>
</html>

template.jsp

<input v-model="test_input">
<p>{{ test_input }}</p>

并且javascript代码也需要进行一些修改:

app.js

$(document).bind("pageshow", function() {
  $.mobile.loading("show");
  $.ajax({
    url: "template.jsp",
    method: "Get",
    data: {
      // My JSPs are parameterized, so the template may
      // need some of the parameters from this page to 
      // be passed down into the template for initialization.
    }
  }).done(function(template) {
    initialize_vue_from_template("#vue-application", template);
  }).always(function() {
    $.mobile.loading("hide");
  });
});

function initialize_vue_from_template(element, template) {
  $(element)
      .html(template)
      // Don't forget to initialize jQuery
      .enhanceWithin(); 

  new Vue({
    el: element,
    data: {
      test_input: ""
    }
  });
}

这似乎有效。我怀疑这是否是一个很好的解决方案,但是我认为它是否可以正常工作,我不妨将其包含在此处。如果有更好的方法可以做到这一点,我很想听听。